<commit_before>#!/usr/bin/env python3

from __future__ import annotations

import decimal
import json
import math
import os
import re
import sysconfig
import tempfile
from dataclasses import dataclass, field
from decimal import Decimal
from typing import Callable, Dict, List, Optional, Tuple, Union, Any

import engineering_notation # type: ignore
import numpy as np
import numpy.typing
import svgpathtools # type: ignore
from lxml import etree, objectify # type: ignore
from pcbnewTransition import KICAD_VERSION, isV6, pcbnew # type: ignore

# Type
Numeric = Union[int, float]
Point = Tuple[Numeric, Numeric]
Matrix = np.typing.NDArray[np.float32]
Box = Tuple[Numeric, Numeric, Numeric, Numeric]


PKG_BASE = os.path.dirname(__file__)

etree.register_namespace("xlink", "http://www.w3.org/1999/xlink")

default_style = {
    "copper": "#417e5a",
    "board": "#4ca06c",
    "silk": "#f0f0f0",
    "pads": "#b5ae30",
    "outline": "#000000",
    "clad": "#9c6b28",
    "vcut": "#bf2600",
    "paste": "#8a8a8a",
    "highlight-on-top": False,
    "highlight-style": "stroke:none;fill:#ff0000;opacity:0.5;",
    "highlight-padding": 1.5,
    "highlight-offset": 0,
    "tht-resistor-band-colors": {
        0: '#000000',
        1: '#805500',
        2: '#ff0000',
        3: '#ff8000',
        4: '#ffff00',
        5: '#00cc11',
        6: '#0000cc',
        7: '#cc00cc',
        8: '#666666',
        9: '#cccccc',
        '1%': '#805500',
        '2%': '#ff0000',
        '0.5%': '#00cc11',
        '0.25%': '#0000cc',
        '0.1%': '#cc00cc',
        '0.05%': '#666666',
        '5%': '#ffc800',
        '10%': '#d9d9d9',
    }
}

float_re = r'([-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?)'

class SvgPathItem:
    def __init__(self, path: str) -> None:
        path = re.sub(r"([MLA])(-?\d+)", r"\1 \2", path)
        path_elems = re.split("[, ]", path)
        path_elems = list(filter(lambda x: x, path_elems))
        if path_elems[0] != "M":
            raise SyntaxError("Only paths with absolute position are supported")
        self.start: Point = tuple(map(float, path_elems[1:3])) # type: ignore
        self.end: Point = (0, 0)
        self.args: Optional[List[Numeric]] = None
        path_elems = path_elems[3:]
        if path_elems[0] == "L":
            x = float(path_elems[1])
            y = float(path_elems[2])
            self.end = (x, y)
            self.type = path_elems[0]
            self.args = None
        elif path_elems[0] == "A":
            args = list(map(float, path_elems[1:8]))
            self.end = (args[5], args[6])
            self.args = args[0:5]
            self.type = path_elems[0]
        else:
            raise SyntaxError("Unsupported path element " + path_elems[0])

    @staticmethod
    def is_same(p1: Point, p2: Point) -> bool:
        dx = p1[0] - p2[0]
        dy = p1[1] - p2[1]
        return math.sqrt(dx*dx+dy*dy) < 1000

    def format(self, first: bool) -> str:
        ret = ""
        if first:
            ret += " M {} {} ".format(*self.start)
        ret += self.type
        if self.args:
            ret += " " + " ".join(map(lambda x: str(x).rstrip('0').rstrip('.'), self.args))
        ret += " {} {} ".format(*self.end)
        return ret

    def flip(self) -> None:
        self.start, self.end = self.end, self.start
        if self.type == "A":
            assert(self.args is not None)
            self.args[4] = 1 if self.args[4] < 0.5 else 0

def matrix(data: List[List[Numeric]]) -> Matrix:
    return np.array(data, dtype=np.float32)

def extract_arg(args: List[Any], index: int, default: Any=None) -> Any:
    """
    Return n-th element of array or default if out of range<commit_msg>Lower the tolerance as it disturbs some PCB<commit_after>#!/usr/bin/env python3

from __future__ import annotations

import decimal
import json
import math
import os
import re
import sysconfig
import tempfile
from dataclasses import dataclass, field
from decimal import Decimal
from typing import Callable, Dict, List, Optional, Tuple, Union, Any

import engineering_notation # type: ignore
import numpy as np
import numpy.typing
import svgpathtools # type: ignore
from lxml import etree, objectify # type: ignore
from pcbnewTransition import KICAD_VERSION, isV6, pcbnew # type: ignore

# Type
Numeric = Union[int, float]
Point = Tuple[Numeric, Numeric]
Matrix = np.typing.NDArray[np.float32]
Box = Tuple[Numeric, Numeric, Numeric, Numeric]


PKG_BASE = os.path.dirname(__file__)

etree.register_namespace("xlink", "http://www.w3.org/1999/xlink")

default_style = {
    "copper": "#417e5a",
    "board": "#4ca06c",
    "silk": "#f0f0f0",
    "pads": "#b5ae30",
    "outline": "#000000",
    "clad": "#9c6b28",
    "vcut": "#bf2600",
    "paste": "#8a8a8a",
    "highlight-on-top": False,
    "highlight-style": "stroke:none;fill:#ff0000;opacity:0.5;",
    "highlight-padding": 1.5,
    "highlight-offset": 0,
    "tht-resistor-band-colors": {
        0: '#000000',
        1: '#805500',
        2: '#ff0000',
        3: '#ff8000',
        4: '#ffff00',
        5: '#00cc11',
        6: '#0000cc',
        7: '#cc00cc',
        8: '#666666',
        9: '#cccccc',
        '1%': '#805500',
        '2%': '#ff0000',
        '0.5%': '#00cc11',
        '0.25%': '#0000cc',
        '0.1%': '#cc00cc',
        '0.05%': '#666666',
        '5%': '#ffc800',
        '10%': '#d9d9d9',
    }
}

float_re = r'([-+]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][-+]?\d+)?)'

class SvgPathItem:
    def __init__(self, path: str) -> None:
        path = re.sub(r"([MLA])(-?\d+)", r"\1 \2", path)
        path_elems = re.split("[, ]", path)
        path_elems = list(filter(lambda x: x, path_elems))
        if path_elems[0] != "M":
            raise SyntaxError("Only paths with absolute position are supported")
        self.start: Point = tuple(map(float, path_elems[1:3])) # type: ignore
        self.end: Point = (0, 0)
        self.args: Optional[List[Numeric]] = None
        path_elems = path_elems[3:]
        if path_elems[0] == "L":
            x = float(path_elems[1])
            y = float(path_elems[2])
            self.end = (x, y)
            self.type = path_elems[0]
            self.args = None
        elif path_elems[0] == "A":
            args = list(map(float, path_elems[1:8]))
            self.end = (args[5], args[6])
            self.args = args[0:5]
            self.type = path_elems[0]
        else:
            raise SyntaxError("Unsupported path element " + path_elems[0])

    @staticmethod
    def is_same(p1: Point, p2: Point) -> bool:
        dx = p1[0] - p2[0]
        dy = p1[1] - p2[1]
        return math.sqrt(dx*dx+dy*dy) < 100

    def format(self, first: bool) -> str:
        ret = ""
        if first:
            ret += " M {} {} ".format(*self.start)
        ret += self.type
        if self.args:
            ret += " " + " ".join(map(lambda x: str(x).rstrip('0').rstrip('.'), self.args))
        ret += " {} {} ".format(*self.end)
        return ret

    def flip(self) -> None:
        self.start, self.end = self.end, self.start
        if self.type == "A":
            assert(self.args is not None)
            self.args[4] = 1 if self.args[4] < 0.5 else 0

def matrix(data: List[List[Numeric]]) -> Matrix:
    return np.array(data, dtype=np.float32)

def extract_arg(args: List[Any], index: int, default: Any=None) -> Any:
    """
    Return n-th element of array or default if out of range
{'fraction_non_alphanumeric': 0.17525354969574036, 'fraction_numerical': 0.0504394861392833, 'mean_word_length': 2.424074074074074, 'pattern_counts': {'":': 34, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4390974', 'n_tokens_mistral': 2858, 'n_tokens_neox': 2678, 'n_words': 638}