#!/usr/bin/python
#
# This is a script for dumping and changing peripheral settings on an STM32
# on a running target with he help of OpenOCD. It was written for reverse
# engineering the DPS5005 but should work for any STM32 target with little
# change.
#
# No rights reserved
#

import socket
import sys

prompt = "> " # OpenOCD prompt

ocd_sock = False

def ocd_exchange(str = ""):
    output = ""
    line = ""
    got_prompt = False
    if len(str) > 0:
        ocd_sock.send(bytearray(str, "ascii"))
    while 1:
        try:
            ch = ocd_sock.recv(1)
            if len(ch) > 0:
                if ch == b'\d':
                    pass
                if ch == b'\n':
                    if "%s\n" % line != str:
                        output += "%s\n" % line
                    line = ""
                elif ord(ch) >= 32 and ord(ch) <= 126:
                    line += ch.decode("ascii")
                if line.endswith(prompt):
                    got_prompt = True
                    break
            else:
                break
        except socket.timeout as e:
            break
    return output.strip()

def ocd_sync():
    return ocd_exchange()

def ocd_read(address):
    response = ocd_exchange("mdw 0x%08x 1\n" % (address))
    parts = response.split(":")
    if len(parts) != 2:
        print ("Parsing error: %s" % response)
        return False
    temp_address = int(parts[0].strip(), 16)
    value = int(parts[1].strip(), 16)
    if temp_address != address:
        print ("Address error: %s" % response)
        return False
    return value

def ocd_write(address, value):
    response = ocd_exchange("mww 0x%08x 0x%08x\n" % (address, value))

known_pins = {
    "PA0"  : ["", "U7 "],
    "PA1"  : ["M2 button", ""],
    "PA2"  : ["SEL button", ""],
    "PA3"  : ["M1 button", ""],
    "PA4"  : ["DAC1_OUT", "TL594.2 (1IN-)"],
    "PA5"  : ["DAC2_OUT", "TL594.15 (2IN-)"],
    "PA7"  : ["ADC1_IN7", "R30-U2.7:V_OUT-B (measures Vout)"],
    "PA8"  : ["TFT.7", "(not used by TFT)"],
    "PA14" : ["", "SWDCLK"],
    "PA15" : ["", "R41-TL594.16 (2IN+)"],
    "PB0"  : ["ADC1_IN8", "R7/R2-R14-D4 (measures Vin)"],
    "PB1"  : ["ADC1_IN9", "R33-U2.1:V_OUT-A (measures Iout)"],
    "PB3"  : ["", "R11-R17-R25-U2.5 (V_inB+)"],
    "PB4"  : ["PWR button", ""],
    "PB5"  : ["Rotary press", ""],
    "PB6"  : ["", "NC?"],
    "PB7"  : ["TIM4_CH2", ""],
    "PB8"  : ["Rotary enc", ""],
    "PB9"  : ["Rotary enc", ""],
    "PB11" : ["nPwrEnable", "R29-TFT.2 (TFT_VCC)"],
    "PB12" : ["SPI2_NSS", "TFT_RESET"],
    "PB13" : ["SPI2_SCK", ""],
    "PB14" : ["SPI2_MISO", "TFT_A0"],
    "PB15" : ["SPI2_MOSI", ""],
    "PD1"  : ["", "U7"],
}

ADC1_BASE  = 0x40012400
AFIO_BASE  = 0x40010000
DAC_BASE   = 0x40007400
DMA1_BASE  = 0x40020000
EXTI_BASE  = 0x40010400
GPIOA_BASE = 0x40010800
GPIOB_BASE = 0x40010c00
GPIOC_BASE = 0x40011000
GPIOD_BASE = 0x40011400
GPIOE_BASE = 0x40011800
GPIOF_BASE = 0x40011C00
GPIOG_BASE = 0x40012000
RCC_BASE   = 0x40021000
SPI1_BASE  = 0x40013000
SPI2_BASE  = 0x40003800
TIM1_BASE  = 0x40012C00
TIM2_BASE  = 0x40000000
TIM3_BASE  = 0x40000400
TIM4_BASE  = 0x40000800
TIM6_BASE  = 0x40001000
TIM7_BASE  = 0x40001400
TIM15_BASE = 0x40014000
TIM16_BASE = 0x40014400
TIM17_BASE = 0x40014800

# SPI1 registers
SPI_CR1 = 0x00
SPI_CR2 = 0x04
SPI_SR = 0x08
SPI_DR = 0x0C
SPI_CRCPR = 0x10
SPI_RXCRCR = 0x14
SPI_TXCRCR = 0x18

# TIM2 to TIM5 registers (checked)
TIMx_CR1   = 0x00
TIMx_CR2   = 0x04
TIMx_SMC   = 0x08
TIMx_DIER  = 0x0c
TIMx_SR    = 0x10
TIMx_EGR   = 0x14
TIMx_CCMR1 = 0x18
TIMx_CCMR2 = 0x1c
TIMx_CCER  = 0x20
TIMx_CNT   = 0x24
TIMx_PSC   = 0x28
TIMx_ARR   = 0x2c
TIMx_RCR   = 0x30
TIMx_CCR1  = 0x34
TIMx_CCR2  = 0x38
TIMx_CCR3  = 0x3c
TIMx_CCR4  = 0x40
TIMx_BDTR  = 0x44
TIMx_DCR   = 0x48
TIMx_DMAR  = 0x4c

# ADC registers (checked)
ADC_SR    = 0x00
ADC_CR1   = 0x04
ADC_CR2   = 0x08
ADC_SMPR1 = 0x0C
ADC_SMPR2 = 0x10
ADC_JOFR1 = 0x14
ADC_JOFR2 = 0x18
ADC_JOFR3 = 0x1C
ADC_JOFR4 = 0x20
ADC_HTR   = 0x24
ADC_LTR   = 0x28
ADC_SQR1  = 0x2C
ADC_SQR2  = 0x30
ADC_SQR3  = 0x34
ADC_JSQR  = 0x38
ADC_JDR1  = 0x3C
ADC_JDR2  = 0x40
ADC_JDR3  = 0x44
ADC_JDR4  = 0x48
ADC_DR    = 0x4C

# DAC registers (checked)
DAC_CR      = 0x00
DAC_SWTRIGR = 0x04
DAC_DHR12R1 = 0x08
DAC_DHR12L1 = 0x0C
DAC_DHR8R1  = 0x10
DAC_DHR12R2 = 0x14
DAC_DHR12L2 = 0x18
DAC_DHR8R2  = 0x1c
DAC_DHR12RD = 0x20
DAC_DHR12LD = 0x24
DAC_DHR8RD  = 0x28
DAC_DOR1    = 0x2C
DAC_DOR2    = 0x30
DAC_SR      = 0x34

# GPIO registers (checked)
GPIOx_CRL    = 0x00
GPIOx_CRH    = 0x04
GPIOx_IDR    = 0x08
GPIOx_ODR    = 0x0c
GPIOx_BSRR   = 0x10
GPIOx_BRR    = 0x14
GPIOx_LCKR   = 0x18

# EXTI registers (checked)
EXTI_IMR     = 0x00
EXTI_EMR     = 0x04
EXTI_RTSR    = 0x08
EXTI_FTSR    = 0x0c
EXTI_SWIER   = 0x10
EXTI_PR      = 0x14

# AFIO registers (checked)
AFIO_EVCR    = 0x00
AFIO_MAPR    = 0x04
AFIO_EXTICR1 = 0x08
AFIO_EXTICR2 = 0x0c
AFIO_EXTICR3 = 0x10
AFIO_EXTICR4 = 0x14
AFIO_MAPR2   = 0x18

# RCC registers (checked)
RCC_CR       = 0x00
RCC_CFGR     = 0x04
RCC_CIR      = 0x08
RCC_APB2RSTR = 0x0c
RCC_APB1RSTR = 0x10
RCC_AHBENR   = 0x14
RCC_APB2ENR  = 0x18
RCC_APB1ENR  = 0x1c
RCC_BDCR     = 0x20
RCC_CSR      = 0x24
RCC_CFGR2    = 0x2c

# DMA registers (checked)
DMA_ISR      = 0x00
DMA_IFCR     = 0x04
DMA_CCR1     = 0x08
DMA_CNDTR    = 0x0C
DMA_CPAR1    = 0x10
DMA_CMAR1    = 0x14
#             0x18
DMA_CCR2     = 0x1C
DMA_CNDTR    = 0x20
DMA_CPAR2    = 0x24
DMA_CMAR2    = 0x28
#              0x2C
DMA_CCR3     = 0x30
DMA_CNDTR    = 0x34
DMA_CPAR3    = 0x38
DMA_CMAR3    = 0x3C
#              0x40
DMA_CCR4     = 0x44
DMA_CNDTR    = 0x48
DMA_CPAR4    = 0x4C
DMA_CMAR4    = 0x50
#              0x54
DMA_CCR5     = 0x58
DMA_CNDTR    = 0x5C
DMA_CPAR5    = 0x60
DMA_CMAR5    = 0x64
#              0x68
DMA_CCR6     = 0x6C
DMA_CNDTR    = 0x70
DMA_CPAR6    = 0x74
DMA_CMAR6    = 0x78
#              0x7C
DMA_CCR7     = 0x80
DMA_CNDTR    = 0x84
DMA_CPAR7    = 0x88

register_map = [
  [0x40023000, 0x400233FF, "CRC"],
  [0x40022000, 0x400223FF, "Flash memory interface"],
  [0x40021000, 0x400213FF, "Reset and clock control RCC"],
  [0x40020000, 0x400203FF, "DMA1"],
  [0x40014800, 0x40014BFF, "TIM17 timer"],
  [0x40014400, 0x400147FF, "TIM16 timer"],
  [0x40014000, 0x400143FF, "TIM15 timer"],
  [0x40013800, 0x40013BFF, "USART1"],
  [0x40013000, 0x400133FF, "SPI1"],
  [0x40012C00, 0x40012FFF, "TIM1 timer"],
  [0x40012400, 0x400127FF, "ADC1"],
  [0x40011800, 0x40011BFF, "GPIO Port E"],
  [0x40011400, 0x400117FF, "GPIO Port D"],
  [0x40011000, 0x400113FF, "GPIO Port C"],
  [0x40010C00, 0x40010FFF, "GPIO Port B"],
  [0x40010800, 0x40010BFF, "GPIO Port A"],
  [0x40010400, 0x400107FF, "EXTI"],
  [0x40010000, 0x400103FF, "AFIO"],
  [0x40007800, 0x40007BFF, "CEC"],
  [0x40007400, 0x400077FF, "DAC"],
  [0x40007000, 0x400073FF, "Power control PWR"],
  [0x40006C00, 0x40006FFF, "Backup registers (BKP)"],
  [0x40005800, 0x40005BFF, "I2C2"],
  [0x40005400, 0x400057FF, "I2C1"],
  [0x40004800, 0x40004BFF, "USART3"],
  [0x40004400, 0x400047FF, "USART2"],
  [0x40003800, 0x40003BFF, "SPI2"],
  [0x40003000, 0x400033FF, "Independent watchdog (IWDG)"],
  [0x40002C00, 0x40002FFF, "Window watchdog (WWDG)"],
  [0x40002800, 0x40002BFF, "RTC"],
  [0x40001400, 0x400017FF, "TIM7 timer"],
  [0x40001000, 0x400013FF, "TIM6 timer"],
  [0x40000800, 0x40000BFF, "TIM4 timer"],
  [0x40000400, 0x400007FF, "TIM3 timer"],
  [0x40000000, 0x400003FF, "TIM2 timer"]
]

port_addresses = [GPIOA_BASE, GPIOB_BASE, GPIOC_BASE, GPIOD_BASE, GPIOE_BASE, GPIOF_BASE, GPIOG_BASE]

CRL_CNF_IN = ["An", "Flt", "PuPd", "RFU"]
CRL_CNF_IN_ANALOG = 0
CRL_CNF_IN_FLOAT = 1
CRL_CNF_IN_PUPD = 2
CRL_CNF_IN_RFU = 3

CRL_CNF_OUT = ["PP", "OD", "AF-PP", "AF-OD"]
CRL_CNF_OUT_PP = 0
CRL_CNF_OUT_OD = 1
CRL_CNF_OUT_AF_PP = 2
CRL_CNF_OUT_AF_OD = 3

CRL_MODE = [0, 10, 2, 50]
CRL_MODE_IN = 0
CRL_MODE_OUT_10MHZ = 1
CRL_MODE_OUT_2MHZ = 2
CRL_MODE_OUT_50MHZ = 3

def print_gpio_pin(port_nbr, pin, cnf, mode, level):
    cnf_i = ["GPIO_CNF_INPUT_ANALOG", "GPIO_CNF_INPUT_FLOAT", "GPIO_CNF_INPUT_PULL_UPDOWN", "##### RESERVED #####"]
    cnf_o = ["GPIO_CNF_OUTPUT_PUSHPULL", "GPIO_CNF_OUTPUT_OPENDRAIN", "GPIO_CNF_OUTPUT_ALTFN_PUSHPULL", "GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN"]
    modes = ["GPIO_MODE_INPUT", "GPIO_MODE_OUTPUT_10_MHZ", "GPIO_MODE_OUTPUT_2_MHZ", "GPIO_MODE_OUTPUT_50_MHZ"]

    if mode == 0:
        cnfs = cnf_i
    else:
        cnfs = cnf_o
    a = "gpio_set_mode(GPIO%c, %s, %s, GPIO%d);\n" % (ord('A')+port_nbr, modes[mode], cnfs[cnf], pin)
    if mode == 0 and cnf == 2:
        if level == 0:
            a += "gpio_clear(GPIO%c, GPIO%d);\n" % (ord('A')+port_nbr, pin)
        elif level == 1:
            a += "gpio_set(GPIO%c, GPIO%d);\n" % (ord('A')+port_nbr, pin)
        else:
            a += "rusk!!!!!!!!"
    return a

def dump_port_settings(port_nbr):
#    print("Checking GPIO%c" % (ord('A') + port_nbr))
    crl = ocd_read(port_addresses[port_nbr] + GPIOx_CRL)
    crh = ocd_read(port_addresses[port_nbr] + GPIOx_CRH)
    idr = ocd_read(port_addresses[port_nbr] + GPIOx_IDR)
    odr = ocd_read(port_addresses[port_nbr] + GPIOx_ODR)
    for pin in range(0, 16):
        if pin < 8:
            mode = (crl >> (4*pin)) & 3
            cnf = (crl >> (4*pin+2)) & 3
        else:
            mode = (crh >> (4*(pin-8))) & 3
            cnf = (crh >> (4*(pin-8)+2)) & 3
        pin_s = "P%c%d" % (ord('A')+port_nbr, pin)
        if mode == CRL_MODE_IN:
            level = (idr >> pin) & 1
            info = "%-4s I %d %-5s" % (pin_s, level, CRL_CNF_IN[cnf])
        else:
            level = (odr >> pin) & 1
            info = "%-4s O %d %-5s  (%d Mhz)" % (pin_s, level, CRL_CNF_OUT[cnf], CRL_MODE[mode])
        if pin_s in known_pins:
            desc = known_pins[pin_s]
        else:
            desc = ["", ""]
        setting = print_gpio_pin(port_nbr, pin, cnf, mode, level)
        print("// %-30s %-15s %s" % (info, desc[0], desc[1]))
        print("%s" % (setting))

def dump_gpio_port_settings():
    for port in range(0, 4):
        dump_port_settings(port)

def dump_reg(name, address):
    value = ocd_read(address)
    print("%-8s : 0x%08x  [0x%08x]" % (name, value, address))

"""
CR1      : 0x00000081  [00] ARPE=1 CEN=1
CR2      : 0x00000000  [04]
SMCR     : 0x00000000  [08]
DIER     : 0x00000000  [0c]
SR       : 0x0000001f  [10] CC4IF=1 CC3IF=1 CC2IF=1 CC1IF=1 UIF=1
EGR      : 0x00000000  [14]
CCMR1    : 0x00006800  [18] OC2M=2 OC2PE=1
CCMR2    : 0x00000000  [1c]
CCER     : 0x00000010  [20] CC2P=1
CNT      : 0x000056ed  [24] <counter>
PSC      : 0x00000000  [28]
ARR      : 0x00005dbf  [2c] <auto reload>
CCR1     : 0x00000000  [34]
CCR2     : 0x00005dc0  [38] <TIM2 compare register 2>
CCR3     : 0x00000000  [3c]
CCR4     : 0x00000000  [40]
DCR      : 0x00000000  [48]
DMAR     : 0x00000081  [4c] DMA address

U           ARR         CCR2
1.00        0x00005dbf  0x00005dc0

"""

def dump_tim_settings(name, base_addr):
    print("%s settings" % (name))
    dump_reg("CR1",   base_addr + TIMx_CR1)
    dump_reg("CR2",   base_addr + TIMx_CR2)
    dump_reg("SMC",   base_addr + TIMx_SMC)
    dump_reg("DIER",  base_addr + TIMx_DIER)
    dump_reg("SR",    base_addr + TIMx_SR)
    dump_reg("EGR",   base_addr + TIMx_EGR)
    dump_reg("CCMR1", base_addr + TIMx_CCMR1)
    dump_reg("CCMR2", base_addr + TIMx_CCMR2)
    dump_reg("CCER",  base_addr + TIMx_CCER)
    dump_reg("CNT",   base_addr + TIMx_CNT)
    dump_reg("PSC",   base_addr + TIMx_PSC)
    dump_reg("ARR",   base_addr + TIMx_ARR)
    dump_reg("RCR",   base_addr + TIMx_RCR)
    dump_reg("CCR1",  base_addr + TIMx_CCR1)
    dump_reg("CCR2",  base_addr + TIMx_CCR2)
    dump_reg("CCR3",  base_addr + TIMx_CCR3)
    dump_reg("CCR4",  base_addr + TIMx_CCR4)
    dump_reg("BDTR",  base_addr + TIMx_BDTR)
    dump_reg("DCR",   base_addr + TIMx_DCR)
    dump_reg("DMAR",  base_addr + TIMx_DMAR)
"""
    TIM4 settings

    CR1      : 0x00000081  [0x40000800]
    CR2      : 0x00000000  [0x40000804]
    SMC      : 0x00000000  [0x40000808]
    DIER     : 0x00000000  [0x4000080c]
    SR       : 0x0000001f  [0x40000810]
    EGR      : 0x00000000  [0x40000814]
    CCMR1    : 0x00006800  [0x40000818]
    CCMR2    : 0x00000000  [0x4000081c]
    CCER     : 0x00000010  [0x40000820]
    CNT      : 0x00000ebb  [0x40000824]
    PSC      : 0x00000000  [0x40000828]
    ARR      : 0x00005dbf  [0x4000082c]
    RCR      : 0x00000000  [0x40000830]
    CCR1     : 0x00000000  [0x40000834]
    CCR2     : 0x00001f40  [0x40000838]
    CCR3     : 0x00000000  [0x4000083c]
    CCR4     : 0x00000000  [0x40000840]
    BDTR     : 0x00000000  [0x40000844]
    DCR      : 0x00000000  [0x40000848]
    DMAR     : 0x00000081  [0x4000084c]
"""
def dump_tim4_settings():
    dump_tim_settings("TIM4", TIM4_BASE) # TFT backlight intensity

def dump_dac_settings():
    print("DAC settings")
    dump_reg("CR",      DAC_BASE + DAC_CR)
    dump_reg("SWTRIGR", DAC_BASE + DAC_SWTRIGR)
    dump_reg("DHR12R1", DAC_BASE + DAC_DHR12R1)
    dump_reg("DHR12L1", DAC_BASE + DAC_DHR12L1)
    dump_reg("DHR8R1",  DAC_BASE + DAC_DHR8R1)
    dump_reg("DHR12R2", DAC_BASE + DAC_DHR12R2)
    dump_reg("DHR12L2", DAC_BASE + DAC_DHR12L2)
    dump_reg("DHR8R2",  DAC_BASE + DAC_DHR8R2)
    dump_reg("DHR12RD", DAC_BASE + DAC_DHR12RD)
    dump_reg("DHR12LD", DAC_BASE + DAC_DHR12LD)
    dump_reg("DHR8RD",  DAC_BASE + DAC_DHR8RD)
    dump_reg("DOR1",    DAC_BASE + DAC_DOR1)
    dump_reg("DOR2",    DAC_BASE + DAC_DOR2)
    dump_reg("SR",      DAC_BASE + DAC_SR)
"""
    DAC settings

    CR       : 0x00030003  [0x40007400]
    SWTRIGR  : 0x00000000  [0x40007404]
    DHR12R1  : 0x00000003  [0x40007408]
    DHR12L1  : 0x00000030  [0x4000740c]
    DHR8R1   : 0x00000000  [0x40007410]
    DHR12R2  : 0x0000008c  [0x40007414]
    DHR12L2  : 0x000008c0  [0x40007418]
    DHR8R2   : 0x00000008  [0x4000741c]
    DHR12RD  : 0x008c0003  [0x40007420]
    DHR12LD  : 0x08c00030  [0x40007424]
    DHR8RD   : 0x00000800  [0x40007428]
    DOR1     : 0x00000003  [0x4000742c]
    DOR2     : 0x0000008c  [0x40007430]
    SR       : 0x00000000  [0x40007434]
"""

def dump_adc1_settings():
    print("ADC1 settings")
    dump_reg("SR",      ADC1_BASE + ADC_SR)
    dump_reg("CR1",     ADC1_BASE + ADC_CR1)
    dump_reg("CR2",     ADC1_BASE + ADC_CR2)
    dump_reg("SMPR1",   ADC1_BASE + ADC_SMPR1)
    dump_reg("SMPR2",   ADC1_BASE + ADC_SMPR2)
    dump_reg("JOFR1",   ADC1_BASE + ADC_JOFR1)
    dump_reg("JOFR2",   ADC1_BASE + ADC_JOFR2)
    dump_reg("JOFR3",   ADC1_BASE + ADC_JOFR3)
    dump_reg("JOFR4",   ADC1_BASE + ADC_JOFR4)
    dump_reg("HTR",     ADC1_BASE + ADC_HTR)
    dump_reg("LTR",     ADC1_BASE + ADC_LTR)
    dump_reg("SQR1",    ADC1_BASE + ADC_SQR1)
    dump_reg("SQR2",    ADC1_BASE + ADC_SQR2)
    dump_reg("SQR3",    ADC1_BASE + ADC_SQR3)
    dump_reg("JSQR",    ADC1_BASE + ADC_JSQR)
    dump_reg("JDR1",    ADC1_BASE + ADC_JDR1)
    dump_reg("JDR2",    ADC1_BASE + ADC_JDR2)
    dump_reg("JDR3",    ADC1_BASE + ADC_JDR3)
    dump_reg("JDR4",    ADC1_BASE + ADC_JDR4)
    dump_reg("DR",      ADC1_BASE + ADC_DR)
"""
    ADC1 settings

    SR       : 0x00000010  [0x40012400]
    CR1      : 0x00000000  [0x40012404]
    CR2      : 0x009e0001  [0x40012408] # TSVREF:1, EXTTRIG:1, EXTSEL:111 (SWSTART) ADON:1
    SMPR1    : 0x00000000  [0x4001240c]
    SMPR2    : 0x36c00000  [0x40012410]
    JOFR1    : 0x00000000  [0x40012414]
    JOFR2    : 0x00000000  [0x40012418]
    JOFR3    : 0x00000000  [0x4001241c]
    JOFR4    : 0x00000000  [0x40012420]
    HTR      : 0x00000fff  [0x40012424]
    LTR      : 0x00000000  [0x40012428]
    SQR1     : 0x00000000  [0x4001242c]
    SQR2     : 0x00000000  [0x40012430]
    SQR3     : 0x00000008  [0x40012434]
    SQR4     : 0x00000000  [0x40012438]
    JDR1     : 0x00000000  [0x4001243c]
    JDR2     : 0x00000000  [0x40012440]
    JDR3     : 0x00000000  [0x40012444]
    JDR4     : 0x00000000  [0x40012448]
    DR       : 0x000001cc  [0x4001244c]

    DR: 12c     300     5.0
        168     360     6.0
        19f     415     7.0
        1da     474     8.0
        21a     538     9.0
        254     596     10.0
        2ce     718     12.0

    Linear (tested with https://plot.ly/create/)
"""

def dump_afio_settings():
    print("AFIO settings")
    dump_reg("EVCR",     AFIO_BASE + AFIO_EVCR)
    dump_reg("MAPR",     AFIO_BASE + AFIO_MAPR)
    dump_reg("EXTICR1",  AFIO_BASE + AFIO_EXTICR1)
    dump_reg("EXTICR2",  AFIO_BASE + AFIO_EXTICR2)
    dump_reg("EXTICR3",  AFIO_BASE + AFIO_EXTICR3)
    dump_reg("EXTICR4",  AFIO_BASE + AFIO_EXTICR4)
    dump_reg("MAPR2",    AFIO_BASE + AFIO_MAPR2)
"""
    AFIO settings

    EVCR     : 0x00000000  [0x40010000]
    MAPR     : 0x02008000  [0x40010004]
    EXTICR1  : 0x00000000  [0x40010008]
    EXTICR2  : 0x00000011  [0x4001000c]
    EXTICR3  : 0x00000011  [0x40010010]
    EXTICR4  : 0x00000000  [0x40010014]
    MAPR2    : 0x00000000  [0x40010018]
"""

def dump_exti_settings():
    print("EXTI settings")
    dump_reg("IMR",    EXTI_BASE + EXTI_IMR)
    dump_reg("EMR",    EXTI_BASE + EXTI_EMR)
    dump_reg("RTSR",   EXTI_BASE + EXTI_RTSR)
    dump_reg("FTSR",   EXTI_BASE + EXTI_FTSR)
    dump_reg("SWIER",  EXTI_BASE + EXTI_SWIER)
    dump_reg("PR",     EXTI_BASE + EXTI_PR)
"""
    EXTI settings

    IMR      : 0x0000033e  [0x40010400]
    EMR      : 0x00000000  [0x40010404]
    RTSR     : 0x00000300  [0x40010408]
    FTSR     : 0x0000033e  [0x4001040c]
    SWIER    : 0x00000000  [0x40010410]
    PR       : 0x00000000  [0x40010414]
"""

def dump_rcc_settings():
    print("RCC settings")
    dump_reg("CR",       RCC_BASE + RCC_CR)
    dump_reg("CFGR",     RCC_BASE + RCC_CFGR)
    dump_reg("CIR",      RCC_BASE + RCC_CIR)
    dump_reg("APB2RSTR", RCC_BASE + RCC_APB2RSTR)
    dump_reg("APB1RSTR", RCC_BASE + RCC_APB1RSTR)
    dump_reg("AHBENR",   RCC_BASE + RCC_AHBENR)
    dump_reg("APB2ENR",  RCC_BASE + RCC_APB2ENR)
    dump_reg("APB1ENR",  RCC_BASE + RCC_APB1ENR)
    dump_reg("BDCR",     RCC_BASE + RCC_BDCR)
    dump_reg("CSR",      RCC_BASE + RCC_CSR)
    dump_reg("CFGR2",    RCC_BASE + RCC_CFGR2)

def dump_spi_settings(name, base_addr):
    print("%s settings" % (name))
    dump_reg("CR2",      base_addr + SPI_CR1)
    dump_reg("CR1",      base_addr + SPI_CR2)
    dump_reg("SR",       base_addr + SPI_SR)
    dump_reg("DR",       base_addr + SPI_DR)
    dump_reg("CRCPR",    base_addr + SPI_CRCPR)
    dump_reg("RXCRCR",   base_addr + SPI_RXCRCR)
    dump_reg("TXCRCR",   base_addr + SPI_TXCRCR)

def dump_spi1_settings():
    dump_spi_settings("SPI1", SPI1_BASE)

def dump_spi2_settings():
    dump_spi_settings("SPI2", SPI2_BASE)

def dump_gpio_settings(name, base_addr):
    print("%s settings" % (name))
    dump_reg("CRL",      base_addr + GPIOx_CRL)
    dump_reg("CRH",      base_addr + GPIOx_CRH)
    dump_reg("IDR",      base_addr + GPIOx_IDR)
    dump_reg("ODR",      base_addr + GPIOx_ODR)
    dump_reg("BSRR",     base_addr + GPIOx_BSRR)
    dump_reg("BRR",      base_addr + GPIOx_BRR)
    dump_reg("LCKR",     base_addr + GPIOx_LCKR)

def dump_gpioa_settings():
    dump_gpio_settings("GPIOA", GPIOA_BASE)

def dump_gpiob_settings():
    dump_gpio_settings("GPIOB", GPIOB_BASE)

def dump_gpioc_settings():
    dump_gpio_settings("GPIOC", GPIOC_BASE)

def dump_gpiod_settings():
    dump_gpio_settings("GPIOD", GPIOD_BASE)

"""

DAC settings @ 5V :

CR       : 0x00030003  [00] CH 1/2 output buffer disable,  CH 1/2 enable TSEL=000
SWTRIGR  : 0x00000000  [04]
DHR12R1  : 0x00000169  [08] DAC channel1 12-bit right-aligned data holding register
DHR12L1  : 0x00001690  [0c] DAC channel1 12-bit left aligned data holding register
DHR8R1   : 0x00000016  [10] DAC channel1 8-bit right aligned data holding register
DHR12R2  : 0x000001d6  [14] DAC channel2 12-bit right aligned data holding register
DHR12L2  : 0x00001d60  [18] DAC channel2 12-bit left aligned data holding register
DHR8R2   : 0x0000001d  [1c] DAC channel2 8-bit right-aligned data holding register
DHR12RD  : 0x01d60169  [20] Dual DAC 12-bit right-aligned data holding register
DHR12LD  : 0x1d601690  [24] DUAL DAC 12-bit left aligned data holding register
DHR8RD   : 0x00001d16  [28] DUAL DAC 8-bit right aligned data holding register
DOR1     : 0x00000169  [2c] DAC channel1 data output register
DOR2     : 0x000001d6  [30] DAC channel2 data output register
SR       : 0x00000000  [34]

# 470/V

# 0V
mww 0x40007424 0x1d600000

# 1V
mww 0x40007424 0x1d6004D0

# 2V
mww 0x40007424 0x1d600940

# 3V
mww 0x40007424 0x1d600DB0

# 4V
mww 0x40007424 0x1d601220

# 5V
mww 0x40007424 0x1d601690

# 6V
mww 0x40007424 0x1d601B00

# Full swing (Vin - 1V)
mww 0x40007424 0x1d601f40

# 7.10V @ 7.70V matning
mww 0x40007424 0x1d601fff

"""

def dump_dma_settings():
    print("DMA settings")
    dump_reg("ISR",    DMA1_BASE + DMA_ISR)
    dump_reg("IFCR",   DMA1_BASE + DMA_IFCR)
    dump_reg("CCR1",   DMA1_BASE + DMA_CCR1)
    dump_reg("CNDTR",  DMA1_BASE + DMA_CNDTR)
    dump_reg("CPAR1",  DMA1_BASE + DMA_CPAR1)
    dump_reg("CMAR1",  DMA1_BASE + DMA_CMAR1)
    dump_reg("CCR2",   DMA1_BASE + DMA_CCR2)
    dump_reg("CNDTR",  DMA1_BASE + DMA_CNDTR)
    dump_reg("CPAR2",  DMA1_BASE + DMA_CPAR2)
    dump_reg("CMAR2",  DMA1_BASE + DMA_CMAR2)
    dump_reg("CCR3",   DMA1_BASE + DMA_CCR3)
    dump_reg("CNDTR",  DMA1_BASE + DMA_CNDTR)
    dump_reg("CPAR3",  DMA1_BASE + DMA_CPAR3)
    dump_reg("CMAR3",  DMA1_BASE + DMA_CMAR3)
    dump_reg("CCR4",   DMA1_BASE + DMA_CCR4)
    dump_reg("CNDTR",  DMA1_BASE + DMA_CNDTR)
    dump_reg("CPAR4",  DMA1_BASE + DMA_CPAR4)
    dump_reg("CMAR4",  DMA1_BASE + DMA_CMAR4)
    dump_reg("CCR5",   DMA1_BASE + DMA_CCR5)
    dump_reg("CNDTR",  DMA1_BASE + DMA_CNDTR)
    dump_reg("CPAR5",  DMA1_BASE + DMA_CPAR5)
    dump_reg("CMAR5",  DMA1_BASE + DMA_CMAR5)
    dump_reg("CCR6",   DMA1_BASE + DMA_CCR6)
    dump_reg("CNDTR",  DMA1_BASE + DMA_CNDTR)
    dump_reg("CPAR6",  DMA1_BASE + DMA_CPAR6)
    dump_reg("CMAR6",  DMA1_BASE + DMA_CMAR6)
    dump_reg("CCR7",   DMA1_BASE + DMA_CCR7)
    dump_reg("CNDTR",  DMA1_BASE + DMA_CNDTR)
    dump_reg("CPAR7",  DMA1_BASE + DMA_CPAR7)

def dump_register_map():
    global register_map
    for reg in register_map:
        address = reg[0]
        end = reg[1]
        name = reg[2]
        print("\n# %s (0x%08x..0x%08x)" % (name, address, end))
        while address < end:
            value = ocd_read(address)
            print("[0x%08x] = 0x%08x" % (address, value))
            address += 4

def write_mem():
    if len(sys.argv) != 4:
        print("%s <address> <value>" % (sys.argv[0]))
    else:
        address = int(sys.argv[2], 16)
        value = int(sys.argv[3], 16)
        ocd_write(address, value)

def read_mem():
    if len(sys.argv) < 3:
        print("%s <address> [<length>]" % (sys.argv[0]))
    else:
        length = 1
        address = int(sys.argv[2], 16)
        if len(sys.argv) == 4:
            length = int(sys.argv[3], 16)
        while length > 0:
            value = ocd_read(address)
            print("[0x%08x] = 0x%08x" % (address, value))
            address += 4
            length -= 1

def print_help():
    global commands
    print("Available commands:")
    for cmd in commands:
        print("   %s" % (cmd))

def dump_all():
    global commands
    blocklist = ["reg", "all", "r", "w", "help"]
    for cmd in commands:
        if cmd not in blocklist:
            print(">>>> %s" % cmd)
            commands[cmd]()
            print("")

def parse_mem_dump(data):
    lines = data.split('\n')
    for l in lines:
        parts = l.split(":")
        if len(parts) != 2:
            print ("Parsing error: %s" % l)
            return
        address = int(parts[0].strip(), 16)
        parts[1] = parts[1].strip()
        data = parts[1].split(" ")
        for (i, item) in enumerate(data):
            decode_mem(address+4*i, int(item, 16))

try:
    ocd_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ocd_sock.connect(('localhost', 4444))
    ocd_sock.settimeout(1.0)
except socket.error:
    print("Failed connect to Open OCD")
    sys.exit(1)

if not ocd_sync():
    print("Failed to sync with Open OCD")
    sys.exit(1)

commands = {
    "adc1"  : dump_adc1_settings,
    "afio"  : dump_afio_settings,
    "dac"   : dump_dac_settings,
    "dma"   : dump_dma_settings,
    "exti"  : dump_exti_settings,
    "gpio"  : dump_gpio_port_settings,
    "gpioa" : dump_gpioa_settings,
    "gpiob" : dump_gpiob_settings,
    "gpioc" : dump_gpioc_settings,
    "gpiod" : dump_gpiod_settings,
    "reg"   : dump_register_map,
    "rcc"   : dump_rcc_settings,
    "spi1"  : dump_spi1_settings,
    "spi2"  : dump_spi2_settings,
    "tim4"  : dump_tim4_settings,
    "w"     : write_mem,
    "r"     : read_mem,
    "help"  : print_help,
    "all"   : dump_all,
}

if len(sys.argv) >= 2:
    if sys.argv[1] in commands:
        commands[sys.argv[1]]()
    else:
        print_help();
else:
    print_help();


from os import path
import sys
import metavision_designer_engine as mvd_engine
from metavision_designer_engine import Controller
import metavision_designer_cv as mvd_cv
import metavision_designer_core as mvd_core
import metavision_hal as mv_hal
import cv2
from Python.Event_Processor.EventProcessor import EventProcessor
from Python.Log_Luminance import Log_Luminance, Gen_Image
from metavision_designer_core import RoiFilter

# ce fichier est le ficher d'input raw si on choisis de ne pas utiliser la caméra événementielle
input_filename = "../../Movie/Log_Luminance/out_2021-07-07_13-13-28.raw"  # ne fonctionne pas avec ~/

cam = input("Do you want to use cam ? Y or N ")

if cam == "Y" or cam == "y":
    from_file = False
    controller = Controller()

    device = mv_hal.DeviceDiscovery.open('')

    # Add the device interface to the pipeline
    interface = mvd_core.HalDeviceInterface(device)
    controller.add_device_interface(interface)

    cd_producer = mvd_core.CdProducer(interface)

else:
    # input_filename = input("File path from main ")
    from_file = True
    # Check validity of input arguments
    if not (path.exists(input_filename) and path.isfile(input_filename)):
        print("Error: provided input path '{}' does not exist or is not a file.".format(input_filename))
        sys.exit(1)

    is_raw = input_filename.endswith('.raw')

    if not is_raw:
        print("Error: provided input path '{}' does not have the right extension. ".format(input_filename) +
              "It has either to be a .raw or a .dat file")
        sys.exit(1)

    controller = mvd_engine.Controller()

    device = mv_hal.DeviceDiscovery.open_raw_file(input_filename)
    if not device:
        print("Error: could not open file '{}'.".format(input_filename))
        sys.exit(1)

    # Add the device interface to the pipeline
    interface = mvd_core.HalDeviceInterface(device)
    controller.add_device_interface(interface)

    cd_producer = mvd_core.CdProducer(interface)

    # Start the streaming of events
    i_events_stream = device.get_i_events_stream()
    i_events_stream.start()

# Add cd_producer to the pipeline
controller.add_component(cd_producer, "CD Producer")

# Get the sensor size.
geometry = device.get_i_geometry()
width = geometry.get_width()
height = geometry.get_height()
print("Sensor size width = {}   height = {}".format(width, height))

# crop pour la caméra événementielle
roi_width = int(100)
roi_height = int(100)
x0 = int(width / 2 - roi_width / 2)
y0 = int(height / 2 - roi_height / 2)
x1 = x0 + roi_width
y1 = y0 + roi_height
roi_filter = RoiFilter(cd_producer, x0, y0, x1, y1)
controller.add_component(roi_filter)
print("ROI size width = {}   height = {}   Number of pixels = {}".format(roi_width, roi_height, roi_width * roi_height))

# ActivityNoiseFilter configuration
time_window_length = 1500  # duration in us plus c'est bas plus c'est filtré
cd_filtered = mvd_cv.ActivityNoiseFilter(roi_filter, time_window_length)
controller.add_component(cd_filtered, "Noise filter")
filtered_frame_gen = mvd_core.FrameGenerator(cd_filtered)
controller.add_component(filtered_frame_gen, "Filtered frame generator")

# Create Frame Generator with 20ms accumulation time
frame_gen = mvd_core.FrameGenerator(cd_filtered)
frame_gen.set_dt(20000)
controller.add_component(frame_gen, "FrameGenerator")

# We use PythonConsumer to "grab" the output of two components: cd_producer and frame_gen
# pyconsumer will callback the application each time it receives data, using the event_callback function
frame_gen_name = "FrameGen"
cd_prod_name = "CDProd"
ev_proc = EventProcessor(event_gen_name=cd_prod_name, frame_gen_name=frame_gen_name, width=width, height=height,
                         display_callback=False)

pyconsumer = mvd_core.PythonConsumer(ev_proc.event_callback)
pyconsumer.add_source(cd_filtered, cd_prod_name)  # filtered (cd_filtered) or not filtered (cd_producer)
pyconsumer.add_source(filtered_frame_gen, frame_gen_name)  # filtered (filtered_frame_gen) or not filtered (frame_gen)
controller.add_component(pyconsumer, "PythonConsumer")

controller.set_slice_duration(10000)
controller.set_batch_duration(50000)
do_sync = True if from_file else False

# Start the camera
if not from_file:
    simple_device = device.get_i_device_control()
    simple_device.start()

# Start the streaming of events
i_events_stream = device.get_i_events_stream()
i_events_stream.start()

#################################Parameters#################################
# on part du principe que l'image est carré
divide_matrix_by = 2  # de combien on divise la taille de l'image, si on part d'une résolution 100*100 on obtient du 50*50 si divisé par 2
print("divide size width = {}   height = {}   Number of pixels = {}".format(int(roi_width/divide_matrix_by), int(roi_height/divide_matrix_by),
                                                                            int(roi_width/divide_matrix_by) * int(roi_height/divide_matrix_by)))
# les deux matrices de niveaux qui permet de faire fonctionner la log luminance
# on les garde d'un batch à l'autre ce qui fait que si on a qu'un seul gros batch qui contient tous les événements l'algo fonctionne quand même
matrix_level_HQ = Log_Luminance.gen_matrix_PixelState(roi_width, roi_height)  # correspond à la haute résolution
matrix_level_LQ = Log_Luminance.gen_matrix_PixelState(int(roi_width / divide_matrix_by), int(roi_height / divide_matrix_by))  # correspond à la basse résolution

#Make Video
# si ce paramétre est mis en true, on ajoute les image créer à chaque batch dans un tableau puis on les enregistre sur le disque avec le nom spécifié dans nom_video
# le nombre de seconde est le nombre de second que la vidéo va duré, j'ai paramétré la video pour qu'elle soit cadancé à 28fps
# le temps de filmé correspond donc au temps pour acquérir nb_second_de_video*28 images  au total
make_video_at_the_end = False
nb_second_de_video = 15
nom_video = 'ahahah'  # juste mettre le nom, le fichier sortira en .avi à la fin du programme
array_img = []

while not controller.is_done():
    controller.run(do_sync)

    events = ev_proc.get_event()  # tableau d'event
    events_LQ = Log_Luminance.log_luminance(events, matrix_level_HQ, matrix_level_LQ, divide_matrix_by, (width, height),
                                            (roi_width, roi_height), treshold=1, interpolation=0)

    # cette fonction ne marche pas et je ne comprend pas POURQUOI AAAAAAAAHHHHH: elle fonctionne maintenant mais le commentaire me fait sourir
    img_original = ev_proc.get_cut_event_2d_arrays(x0, x1, y0, y1)
    img = Gen_Image.create_image_rgb_from_log_luminance(events_LQ, int(roi_width/divide_matrix_by), int(roi_height/divide_matrix_by))
    img_original = cv2.resize(img_original, (200, 200))
    img = cv2.resize(img, (200, 200))
    cv2.imshow("Original", img_original)
    cv2.imshow("Log Luminance", img)

    # les deux ligne de code en dessous permettes de visualiser le fonctionnement des matrices de niveaux mais consomme beaucoup de ressources
    #cv2.imshow("pixelstateHQ", cv2.resize(Gen_Image.create_image_rgb_from_pixel_state(matrix_level_HQ), (400, 400)))
    #cv2.imshow("pixelstateLQ", cv2.resize(Gen_Image.create_image_rgb_from_pixel_state(matrix_level_LQ), (400, 400)))

    if make_video_at_the_end:
        array_img.append(img)

    cv2.waitKey(1)  # ne jamais oublié cet ligne de code qui empêche l'image de s'afficher si elle n'est pas la

    if nb_second_de_video*28 == len(array_img) and make_video_at_the_end:
        break

cv2.destroyAllWindows()

if make_video_at_the_end:
    Gen_Image.convert_array_of_image_in_video(array_img, nom_video)


from collections import defaultdict
from itertools import permutations

class DinnerTable:
    def __init__(self, instructions) -> None:
        self.ins = instructions
        self.happiness_scores = {}
        self.guest_list = []

    def process_happiness_scores(self):
        lines = [line for line in self.ins.split("\n") if line != ""]
        for line in lines:
            elements = line.split()
            name = elements[0].strip()
            pos_neg = 0
            if elements[2].strip() == "gain":
                pos_neg = 1
            else:
                pos_neg = -1
            score = int(elements[3].strip())
            neighbour = elements[-1][:-1]
            if name not in self.happiness_scores.keys():
                self.happiness_scores[name] = {}
            self.happiness_scores[name].update({neighbour: score * pos_neg})

        self.guest_list = list(self.happiness_scores.keys())

    def add_host_to_happiness_scores(self):
        self.happiness_scores["Host"] = {}
        self.guest_list = list(self.happiness_scores.keys())
        for guest in self.guest_list:
            self.happiness_scores["Host"].update({guest: 0})
            self.happiness_scores[guest].update({"Host": 0})

    def seating_plan_naive(self):
        possible_plans = permutations(self.guest_list)
        possible_plans = [p + (p[0],) for p in possible_plans]

        best_plan = []
        best_plan_score = 0

        for plan in possible_plans:
            happiness = 0
            first = plan[0]
            for neighbour in plan[1:]:
                happiness += self.happiness_scores[first][neighbour]
                happiness += self.happiness_scores[neighbour][first]
                first = neighbour
            if happiness > best_plan_score:
                best_plan_score = happiness
                best_plan = plan
        print(
            f"The happiest plan {best_plan} with a happiness score of {best_plan_score}."
        )

        return best_plan_score

if __name__ == "__main__":
    with open("input.txt", "r") as f:
        instructions = f.read()

    dt = DinnerTable(instructions)
    dt.process_happiness_scores()
    dt.add_host_to_happiness_scores()
    dt.seating_plan_naive()


import os
import argparse
import utils
import json
import numpy as np
from sklearn import metrics
from tqdm import tqdm

import torch
from torch.utils.data import DataLoader
import torchvision.transforms as T

from models.dgcnn import DGCNN
from models.pointnet import PointNet, feature_transform_regularizer
import transforms as transforms
from data import PointCloudDataset

def test(args):
    current_path = os.path.dirname(args.model_path)

    with open(os.path.join(current_path, "settings.txt"), 'r') as f:
        settings = json.load(f)

    args.exp_name = settings["exp_name"]

    args.cuda = torch.cuda.is_available()
    if args.cuda:
        print(
            'Using GPU : ' + str(torch.cuda.current_device()) + ' from ' + str(torch.cuda.device_count()) + ' devices')
        torch.cuda.manual_seed(settings["seed"])
    else:
        print('Using CPU')

    device = torch.device("cuda" if args.cuda else "cpu")

    numClass = settings["num_classes"]
    modelType = settings["model"]

    if modelType == "pointnet":
        model = PointNet(numClass, emb_dims=settings["emb_dims"], dropout_rate=settings["dropout"], feature_transform=settings["transform_regularization"] > 0.0)
    elif modelType =="dgcnn":
        model = DGCNN(numClass, emb_dims=settings["emb_dims"], dropout_rate=settings["dropout"], k=settings["k"])
    else:
        raise Exception("Not implemented")

    model_state_path = os.path.join(current_path, "model_Both_loss.t7")

    # load model
    model = torch.load(model_state_path)
    model.to(device)
    model.eval()

    # DataLoaders
    test_transforms  = T.Compose([transforms.Normalize()])

    test_real_dataset = PointCloudDataset(dataDir = args.data_path, partition='Testing', num_points=1024, transforms = test_transforms, data_type = ["real"], binary_data = False)
    test_synthetic_dataset = PointCloudDataset(dataDir = args.data_path, partition='Testing', num_points=1024, transforms = test_transforms, data_type = ["synthetic"], binary_data = False)
    test_dataset = PointCloudDataset(dataDir = args.data_path, partition='Testing', num_points=1024, transforms = test_transforms, data_type = ["synthetic","real"], binary_data = False)

    test_real_loader = DataLoader(test_real_dataset, num_workers=0, batch_size=args.batch_size, shuffle=False, drop_last=False)
    test_synthetic_loader = DataLoader(test_synthetic_dataset, num_workers=0, batch_size=args.batch_size, shuffle=False, drop_last=False)
    test_loader = DataLoader(test_dataset, num_workers=0, batch_size=args.batch_size, shuffle=False, drop_last=False)

    data_settings = [("Real", test_real_loader), ("Synthetic", test_synthetic_loader), ("All", test_loader)]

    with torch.no_grad():
        for data_setting, data_loader in data_settings:
            predicted_labels = []
            correct_labels = []

            baseDir = os.path.join(current_path, data_setting)
            if not os.path.isdir(baseDir):
                os.makedirs(baseDir)

            incorrectPredDir = os.path.join(baseDir, "incorrect_predictions")
            if not os.path.isdir(incorrectPredDir):
                os.makedirs(incorrectPredDir)

            for data, label in tqdm(data_loader):
                data = data.to(device)
                data = data.float()
                labels = label.to(device).squeeze()

                data = data.permute(0, 2, 1)
                batch_size = data.size()[0]

                if modelType == "pointnet":
                    output, _, _ = model(data)
                else:
                    output = model(data)

                preds = output.max(dim=1)[1]
                correct_labels.append(labels.cpu().numpy())
                predicted_labels.append(preds.detach().cpu().numpy())

                for i in range(len(labels)):
                    if labels[i] != preds[i]:
                        temp_data = data[i].permute(1, 0)

                        num_csvs = len(os.listdir(incorrectPredDir))
                        np.savetxt(os.path.join(incorrectPredDir, "prediction{}_{}.csv".format(labels[i], num_csvs)), temp_data.cpu().numpy())

            correct_labels = np.concatenate(correct_labels)
            predicted_labels = np.concatenate(predicted_labels)
            cm = metrics.confusion_matrix(correct_labels, predicted_labels)
            print(cm)

            precision, recall, f1, support = metrics.precision_recall_fscore_support(correct_labels, predicted_labels, average="weighted")
            normal_accuracy = metrics.accuracy_score(correct_labels, predicted_labels)
            average_accuracy = metrics.balanced_accuracy_score(correct_labels, predicted_labels)

            np.savetxt(os.path.join(baseDir, "ConfusionMatrix.txt"), cm)

            with open(os.path.join(baseDir, "metrics.txt"), "w") as f:
                f.write("Precision: {}\n".format(precision))
                f.write("Recall: {}\n".format(recall))
                f.write("F1: {}\n".format(f1))
                f.write("Support: {}\n".format(support))
                f.write("Average: {}\n".format(normal_accuracy))
                f.write("Balanced Average: {}\n".format(average_accuracy))

            print(precision, recall, f1, support, normal_accuracy, average_accuracy)

if __name__ == '__main__':
    # Training settings
    parser = argparse.ArgumentParser(description='Settings for Point Cloud Classification Test')
    parser.add_argument('--exp_name', type=str, default='', metavar='N',
                        help='Name of the experiment')

    parser.add_argument('--model_path', type=str, default='', metavar='N',
                        help='Pretrained model path')
    parser.add_argument('--data_path', type=str, default='', metavar='N',
                        help='Dataset path')

    parser.add_argument('--batch_size', type=int, default=32, metavar='batch_size',
                        help='Size of batch. (Default: 32)')

    args = parser.parse_args()

    test(args)


import time

# 切换着执行  yield

def worker1():
    # for i in range(n):
    while True:
        print("in worker1")
        yield
        time.sleep(1)

def worker2():
    # for i in range(n):
    while True:
        print("in worker2")
        yield
        time.sleep(1)

if __name__ == '__main__':
    # 调用生成器函数 产生生成器对象
    w1 = worker1()
    w2 = worker2()

    while True:
        next(w1)
        next(w2)

Day01-15 Python基础课程/Day01-15课程与项目/06协程-网络/03-代码/01-使用yield实现协程.py


from typing import TypedDict

from gdbdash.commands import BoolOption, StrOption
from gdbdash.modules import Module
from gdbdash.utils import FileDescriptorOrPath

DashboardOptions = TypedDict(
    "DashboardOptions",
    {
        "text-highlight": StrOption,
        "text-secondary": StrOption,
        "text-divider": StrOption,
        "text-divider-title": StrOption,
        "divider-fill-char": StrOption,
        "show-divider": BoolOption,
    },
)

DashboardModulesDict = dict[FileDescriptorOrPath, list[Module]]

class Dashboard:
    def on_order_changed(self) -> None: ...


""" Crie um programa que crie uma matriz de dimensão 3x3 e preencha com valores lidos pelo teclado.
No final, mostre a matriz na tela, com a formatação correta """

lista = [[],[],[]]
for i in range(3):
    for j in range(3):
        lista[i].append(int(input(f'Digite um valor [{i}][{j}]: ')))
print('\nA matriz dos números digitados é: ')
for pos, i in enumerate(lista):
    for v in lista[pos]:
        print(v, end=' ')
    print()


# make some tests

import os, glob
from pprint import pprint

from importlib import reload

import designspaceProblems
reload(designspaceProblems)

import designspaceProblems.problems
reload(designspaceProblems.problems)
from designspaceProblems.problems import DesignSpaceProblem, allProblems
from designspaceProblems import DesignSpaceChecker
import ufoProcessor
from fontTools.designspaceLib import SourceDescriptor, InstanceDescriptor, AxisDescriptor, DiscreteAxisDescriptor, RuleDescriptor, processRules

from ufoProcessor import DesignSpaceProcessor, getUFOVersion, getLayer
from fontParts.fontshell import RFont

import fontTools
print("fontTools source:", fontTools.__file__)
print("AxisDescriptor class:", AxisDescriptor)

def printProblems(dc):
    for pr in dc.problems:
        print(pr)

testedProblems = {}
def showProblems(dc):
    global testedProblems
    for pr in dc.problems:
        key = (pr.category,pr.problem)
        if not key in testedProblems:
            testedProblems[key] = 0
        testedProblems[key] += 1

def showUntested():
    global testedProblems
    # these problems can't be tested because UFOprocessor already ignores these faults
    untestable = [(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (1,7),
        (2, 4), (2,5), (3, 2),
        (6, 0), (6, 1), (6, 2), (6, 3),
        (4, 5),
    ]
    print("\n\nTested problems")
    app = allProblems()
    for ap in list(app.keys()):
        if ap in testedProblems:
            print("✅", ap, app.get(ap))
        elif ap in untestable:
            print("❔", ap, app.get(ap))
        else:
            print("❌", ap, app.get(ap))

def makeTests():
    path = os.getcwd()
    errs = designspaceProblems.problems.allProblems()

    # empty designspace
    d1 = DesignSpaceProcessor()
    tp = os.path.join(path, "empty.designspace")
    d1.write(tp)
    dc1 = DesignSpaceChecker(tp)
    dc1.checkEverything()
    showProblems(dc1)
    assert (1,0) in dc1.problems    # no axes defined
    assert (2,0) in dc1.problems    # no sources defined
    assert (2,7) in dc1.problems    # no source on default location
    assert (3,10) in dc1.problems    # no instances defined

    # # malformed file
    # d2 = DesignSpaceProcessor()
    # tp = os.path.join(path, "malformed_file.designspace")
    # d2.write(tp)
    # f = open(tp, 'r')
    # d2 = f.read()
    # f.close()
    # d2 += "garbage"*100
    # f = open(tp, 'w')
    # f.write(d2)
    # f.close()
    # dc2 = DesignSpaceChecker(tp)
    # dc2.checkEverything()
    # showProblems(dc2)
    # assert (0,0) in dc2.problems    # no axes defined
    # assert (1,0) in dc2.problems    # no axes defined
    # assert (2,0) in dc2.problems    # no sources defined
    # assert (2,7) in dc2.problems    # no source on default location
    # assert (3,10) in dc2.problems    # no instances defined

    # # malformed axes
    # d3 = DesignSpaceProcessor()
    # tp = os.path.join(path, "malformed_axis.designspace")
    # a31 = AxisDescriptor()
    # a31.name = "snap"
    # a31.minimum = 1000
    # a31.maximum = 1000
    # a31.default = 1000
    # a31.tag = "1111"
    # d3.addAxis(a31)

    # a32 = AxisDescriptor()
    # a32.name = "crackle"
    # a32.minimum = 0
    # a32.maximum = 1000
    # a32.default = -1000
    # a32.tag = "CRCK"
    # d3.addAxis(a32)
    # d3.write(tp)
    # dc3 = DesignSpaceChecker(tp)
    # dc3.checkEverything()
    # showProblems(dc3)
    # assert (1,9) in dc3.problems    # minimum and maximum value are the same
    # assert (1,10) in dc3.problems   # minimum and maximum value are the same
    # assert (2,0) in dc3.problems    # no sources defined
    # assert (2,7) in dc3.problems    # no source on default location
    # assert (3,10) in dc3.problems    # no instances defined

    # designspace with discrete axis
    d4 = DesignSpaceProcessor()
    tp = os.path.join(path, "discrete_axes.designspace")

    # this designspace has 2 axes: one continuous, one discrete
    # we'll add a default for discrete crackle=0, but not a discrete crackle=500
    a41 = AxisDescriptor()
    a41.name = "snap"
    a41.minimum = 0
    a41.maximum = 1000
    a41.default = 0
    a41.tag = "SNAP"
    d4.addAxis(a41)

    a42 = DiscreteAxisDescriptor()
    a42.name = "crackle"
    a42.default = 0
    a42.values = [0, 500]
    a42.tag = "CRCK"
    print(a42.values)
    d4.addAxis(a42)

    s41 = SourceDescriptor()
    s41.location = dict(snap=0, crackle=0)
    s41.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    d4.addSource(s41)

    s42 = SourceDescriptor()
    s42.location = dict(snap=0, crackle=1000)
    s42.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    d4.addSource(s42)

    d4.write(tp)

    dc4 = DesignSpaceChecker(tp)
    dc4.checkEverything()
    printProblems(dc4)
    showProblems(dc4)

    #print("checkLocationForIllegalDiscreteValues", dc4.checkLocationForIllegalDiscreteValues(dict(snap=0,crackle=1000)))
    assert (2,13) in dc4.problems

    #assert (1,0) in dc.problems    # no axes defined
    #assert (2,0) in dc.problems    # no sources defined
    #assert (2,7) in dc.problems    # no source on default location
    #assert (3,10) in dc.problems    # no instances defined

    # ok axis, a source, but no default
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "no_default.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)
    # s1 = SourceDescriptor()
    # s1.location = dict(snap=500)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # d.write(tp)
    # dc = DesignSpaceChecker(tp)
    # dc.checkEverything()
    # showProblems(dc)
    # assert (2,7) in dc.problems    # no source on default location

    # # ok axis, multiple sources on default
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "multiple_defaults.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)
    # s1 = SourceDescriptor()
    # s1.location = dict(snap=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # s2 = SourceDescriptor()
    # s2.location = dict(snap=0)
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s2)
    # d.write(tp)
    # dc = DesignSpaceChecker(tp)
    # dc.checkEverything()
    # showProblems(dc)
    # assert (2,8) in dc.problems        # multiple sources on default location
    # assert (2,1) not in dc.problems    # not: source UFO missing

    # # ok axis, source without location
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "source-without-location.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)
    # s1 = SourceDescriptor()
    # s1.location = dict(snap=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # s2 = SourceDescriptor()
    # s2.location = dict(snap=(10,11))
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s2)
    # d.write(tp)
    # dc = DesignSpaceChecker(tp)
    # dc.checkEverything()
    # showProblems(dc)
    # assert (2,10) in dc.problems        # source location is anisotropic

    # # ok space, no kerning in default
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "no-kerning-in-default.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)
    # s1 = SourceDescriptor()
    # s1.location = dict(snap=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1_no_kerning.ufo')
    # d.addSource(s1)
    # s2 = SourceDescriptor()
    # s2.location = dict(snap=1000)
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s2)
    # d.write(tp)
    # dc = DesignSpaceChecker(tp)
    # dc.checkEverything()
    # showProblems(dc)
    # assert (5,1) in dc.problems    # ok axis, source without location

    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "source-without-location.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)
    # s1 = SourceDescriptor()
    # s1.location = dict(snap=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # s2 = SourceDescriptor()
    # s2.location = dict(snap=(10,11))
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s2)
    # d.write(tp)
    # dc = DesignSpaceChecker(tp)
    # dc.checkEverything()
    # showProblems(dc)
    # assert (2,10) in dc.problems        # source location is anisotropic

    # # ok space, missing UFO
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "source-ufo-missing.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)

    # a2 = AxisDescriptor()
    # a2.name = "pop"
    # a2.minimum = 0
    # a2.maximum = 1000
    # a2.default = 0
    # a2.tag = "pop_"
    # d.addAxis(a1)

    # s1 = SourceDescriptor()
    # s1.location = dict(snap=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # s2 = SourceDescriptor()
    # s2.location = dict(snap=500)
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # s2.layerName = "missing_layer"
    # d.addSource(s2)
    # s3 = SourceDescriptor()
    # s3.location = dict(snap=1000)
    # s3.path = os.path.join(path, 'masters','geometryMaster_missing.ufo')
    # d.addSource(s3)
    # d.write(tp)
    # dc = DesignSpaceChecker(tp)
    # dc.checkEverything()
    # showProblems(dc)
    # assert (2,1) in dc.problems        # source location is anisotropic
    # assert (2,3) in dc.problems        # source layer missing

    # # multiple ssources in same location
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "multiple_sources_on_same_location.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)
    # s1 = SourceDescriptor()
    # #s1.name = "master.1"
    # s1.location = dict(snap=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # #s2.name = "master.2"
    # for i in range(3):
    #     s2 = SourceDescriptor()
    #     s2.location = dict(snap=1500)
    #     s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    #     d.addSource(s2)
    # d.write(tp)
    # dc = DesignSpaceChecker(d)
    # dc.checkEverything()
    # showProblems(dc)

    # # instance without location
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "instance_without_location.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)
    # s1 = SourceDescriptor()
    # #s1.name = "master.1"
    # s1.location = dict(snap=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # #s2.name = "master.2"
    # s2 = SourceDescriptor()
    # s2.location = dict(snap=1000)
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s2)
    # jd = InstanceDescriptor()
    # jd.familyName = None
    # jd.styleName = None
    # jd.location = None
    # jd.path = None
    # d.addInstance(jd)

    # for i in range(3):
    #     jd = InstanceDescriptor()
    #     jd.familyName = "Duped"
    #     jd.styleName = "Duped"
    #     jd.location = dict(snap=666)
    #     jd.path = "some/path.ufo"
    #     d.addInstance(jd)

    # d.write(tp)
    # dc = DesignSpaceChecker(d)
    # dc.checkEverything()
    # showProblems(dc)
    # #assert (3,1) in dc.problems        # instance location missing
    # assert (3,4) in dc.problems        # multiple instances on location*

    # # mapping tests
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "axismapping.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "ok_axis"
    # a1.minimum = 200
    # a1.maximum = 800
    # a1.default = 200
    # a1.tag = "ax01"
    # a1.map = [(200,0), (500, 500), (800, 1000)] # map is ok
    # d.addAxis(a1)

    # a2 = AxisDescriptor()
    # a2.name = "input_regression_axis"
    # a2.minimum = 200
    # a2.maximum = 800
    # a2.default = 500
    # a2.tag = "ax02"
    # a2.map = [(200,100), (190, 150), (800, 200)] # input regresses ok, output ok
    # d.addAxis(a2)

    # a3 = AxisDescriptor()
    # a3.name = "output_regression_axis"
    # a3.minimum = 500
    # a3.maximum = 800
    # a3.default = 600
    # a3.tag = "ax03"
    # a3.map = [(500,0), (600, 500), (700, 700), (800, 690)] # input progresses ok, output regresses
    # d.addAxis(a3)

    # a4 = AxisDescriptor()
    # a4.name = "mixedup_extremes_axis"
    # a4.minimum = 1000
    # a4.maximum = 800
    # a4.default = 0
    # a4.tag = "ax04"
    # d.addAxis(a4)

    # s1 = SourceDescriptor()
    # #s1.name = "master.1"
    # s1.location = dict(ok_axis=a1.default, output_regression_axis=a3.default)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # #s2.name = "master.2"
    # s2 = SourceDescriptor()
    # s2.location = dict(ok_axis=a1.default, output_regression_axis=a3.maximum)
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s2)
    # d.write(tp)
    # dc = DesignSpaceChecker(d)

    # dc.checkEverything()
    # assert (1,11) in dc.problems
    # assert (1,12) in dc.problems
    # showProblems(dc)

    # # ok axis, ok sources
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "viable.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "snap"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "snap"
    # d.addAxis(a1)
    # s1 = SourceDescriptor()
    # #s1.name = "master.1"
    # s1.location = dict(snap=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)
    # #s2.name = "master.2"
    # s2 = SourceDescriptor()
    # s2.location = dict(snap=1000)
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s2)
    # s3 = SourceDescriptor()
    # s3.location = dict(snap=500)
    # s3.path = os.path.join(path, 'masters','geometryMaster3.ufo')   # bad kerning
    # d.addSource(s3)
    # jd = InstanceDescriptor()
    # jd.familyName = "TestFamily"
    # jd.styleName = "TestStyle"
    # jd.location = dict(snap=500)
    # jd.path = os.path.join(path, 'instances','generatedInstance.ufo')
    # d.addInstance(jd)

    # jd = InstanceDescriptor()
    # jd.familyName = None
    # jd.styleName = None
    # jd.location = dict(snap=600)
    # jd.path = os.path.join(path, 'instances','generatedInstance2.ufo')
    # d.addInstance(jd)

    # jd = InstanceDescriptor()
    # jd.familyName = "Aa"
    # jd.styleName = "Bb"
    # jd.location = dict(snap=600)
    # jd.path = None
    # d.addInstance(jd)

    # r1 = RuleDescriptor()
    # r1.name = "rule_no_subs"
    # cd1 = dict(name='lalala', minimum=100, maximum=200)
    # cd2 = dict(name='snap', minimum=10000, maximum=2000)
    # cd3 = dict(name='snap', minimum=10000, maximum=None)    # problem 7,10
    # cd4 = dict(name='snap', minimum=None, maximum=10000)    # problem 7,11
    # r1.conditionSets.append([cd1, cd2, cd3, cd4])
    # d.addRule(r1)

    # r2 = RuleDescriptor()
    # r2.name = "rule_no_conditionset"
    # r2.subs.append(('glyphFour', 'glyphFour'))
    # d.addRule(r2)

    # r3 = RuleDescriptor()
    # r3.name = "rule_values_the_same"
    # cd1 = dict(name='samesees_1', minimum=200, maximum=200)
    # r1.conditionSets.append([cd1, cd1, cd1])
    # r3.subs.append(('glyphFour', 'glyphFour'))
    # d.addRule(r3)

    # # data for 7, 9 rule without a name
    # r4 = RuleDescriptor()
    # r4.name = None
    # cd1 = dict(name='samesees_2', minimum=200, maximum=200)
    # r1.conditionSets.append([cd1, cd1, cd1])
    # r4.subs.append(('glyphFour', 'glyphFour'))
    # d.addRule(r4)

    # d.write(tp)
    # dc = DesignSpaceChecker(d)
    # dc.checkEverything()
    # showProblems(dc)

    # for p in dc.problems:
    #     print(p)

    # assert not dc.hasStructuralProblems()   # minimum working designspace, ready for fonts
    # assert (3,6) in dc.problems        # missing family name
    # assert (3,7) in dc.problems        # missing style name
    # assert (4,1) in dc.problems        # components
    # assert (4,2) in dc.problems        # default glyph is empty, glyphName
    # assert (4,7) in dc.problems        # default glyph is empty, glyphName
    # assert (4,9) in dc.problems        # incompatible constructions for glyph
    # assert (5,0) in dc.problems        # kerning: no kerning in source
    # assert (5,6) in dc.problems        # no kerning groups in source
    # assert (6,4) in dc.problems        # source font unitsPerEm value different from default unitsPerEm
    # assert (7,2) in dc.problems        # source and destination glyphs the same
    # assert (7,3) in dc.problems        # no substition glyphs defined
    # assert (7,4) in dc.problems        # no conditionset defined
    # assert (7,5) in dc.problems        # condition values on unknown axis
    # assert (7,6) in dc.problems        # condition values out of axis bounds

    # #print(tp)
    # for p in dc.problems:
    #     if p == (4,9):
    #         print(p)
    # # badly populated designspace
    # # this system does not have on-axis masters
    # # but a couple of non-aligned off-axis masters.
    # # Varlib will complain
    # d = DesignSpaceProcessor()
    # tp = os.path.join(path, "badly_populated.designspace")
    # a1 = AxisDescriptor()
    # a1.name = "weight"
    # a1.minimum = 0
    # a1.maximum = 1000
    # a1.default = 0
    # a1.tag = "wght"
    # d.addAxis(a1)

    # a2.name = "width"
    # a2.minimum = -500
    # a2.maximum = 500
    # a2.default = 0
    # a2.tag = "wdth"
    # d.addAxis(a2)

    # a3.name = "optical"
    # a3.minimum = 0
    # a3.maximum = 1000
    # a3.default = 0
    # a3.tag = "opsz"
    # d.addAxis(a3)

    # # neutral
    # s1 = SourceDescriptor()
    # s1.location = dict(weight=0, width=0, optical=0)
    # s1.path = os.path.join(path, 'masters','geometryMaster1.ufo')
    # d.addSource(s1)

    # # offaxis master 1
    # s2 = SourceDescriptor()
    # s2.location = dict(width=-500, weight=1000, optical=0)
    # s2.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s2)

    # # offaxis master 2
    # s3 = SourceDescriptor()
    # s3.location = dict(width=0, weight=1000, optical=1000)
    # s3.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s3)

    # # offaxis master 2
    # s4 = SourceDescriptor()
    # s4.location = dict(width=500, weight=1000, optical=1000)
    # s4.path = os.path.join(path, 'masters','geometryMaster2.ufo')
    # d.addSource(s4)

    # d.write(tp)
    # dc = DesignSpaceChecker(d)
    # dc.checkEverything()

    #showProblems(dc)

    showUntested()

def makeEdit(path, find, replace):
    f = open(path, 'r')
    t = f.read()
    f.close()
    t = t.replace(find, replace)
    f = open(path, 'w')
    f.write(t)
    f.close()
makeTests()


from itertools import combinations

def answer(l):
	l.sort(reverse=True)

	for i in range(len(l), 0, -1):
		for c in itertools.combinations(l, i):
			if sum(c) % 3 == 0:
				return int(''.join(map(str, c)))

	return 0


from ase import Atom, Atoms
from ase.units import Bohr
from gpaw import GPAW
from gpaw.test import equal

def test_xc_nonselfconsistentLDA(in_tmp_dir):
    a = 7.5 * Bohr
    n = 16
    atoms = Atoms([Atom('He', (0.0, 0.0, 0.0))], cell=(a, a, a), pbc=True)
    calc = GPAW(gpts=(n, n, n), nbands=1, xc='LDA')
    atoms.calc = calc
    e1 = atoms.get_potential_energy()
    e1ref = calc.get_reference_energy()
    de12 = calc.get_xc_difference({'name': 'PBE', 'stencil': 1})
    calc = GPAW(gpts=(n, n, n), nbands=1, xc={'name': 'PBE', 'stencil': 1})
    atoms.calc = calc
    e2 = atoms.get_potential_energy()
    e2ref = calc.get_reference_energy()
    de21 = calc.get_xc_difference('LDA')
    print(e1ref + e1 + de12, e2ref + e2)
    print(e1ref + e1, e2ref + e2 + de21)
    print(de12, de21)
    equal(e1ref + e1 + de12, e2ref + e2, 0.02)
    equal(e1ref + e1, e2ref + e2 + de21, 0.025)

    calc.write('PBE.gpw')

    de21b = GPAW('PBE.gpw').get_xc_difference('LDA')
    print(de21, de21b)
    equal(de21, de21b, 9e-8)

    energy_tolerance = 0.0007
    equal(e1, -0.0961003634812, energy_tolerance)  # svnversion 5252
    equal(e2, -0.0790249564625, energy_tolerance)  # svnversion 5252


# Opus/UrbanSim urban simulation software.
# Copyright (C) 2010-2011 University of California, Berkeley, 2005-2009 University of Washington
# See opus_core/LICENSE

from opus_core.variables.variable import Variable
from urbansim.functions import attribute_label
from numpy import ones, array, float32

class ln_access_to_workplace_from_residences(Variable):
    """(SUM(Jobs(i) * exp(logsum_DDD(i to this_zone)), for i=zone_1...zone_n), for
        the income type (DDD) of this house) / number_of_DDD_types

        Although, the above fomula is really calculated in zones and passed through gridcell
        to household.
    """
    gc_ln_access_to_workplace_from_residences = "gc_ln_access_to_workplace_from_residences"
    hh_grid_id = "grid_id"

    def dependencies(self):
        return [attribute_label("gridcell", self.gc_ln_access_to_workplace_from_residences),
                attribute_label("household", self.hh_grid_id)
                ]

    def compute(self, dataset_pool):
        return self.get_dataset().get_2d_dataset_attribute('gc_ln_access_to_workplace_from_residences')

from opus_core.tests import opus_unittest
from urbansim.variable_test_toolbox import VariableTestToolbox
from numpy import ma

class Tests(opus_unittest.OpusTestCase):
    variable_name = "urbansim.household_x_gridcell.ln_access_to_workplace_from_residences"

    def test_my_inputs(self):
        values = VariableTestToolbox().compute_variable(self.variable_name,
            {"household":{
                "grid_id": array([1, 2, 3, 1])},
             "gridcell":{
                 "gc_ln_access_to_workplace_from_residences": array([1.1, 11.1, 111.1])}},
            dataset = "household_x_gridcell")

        should_be = array([[1.1, 11.1, 111.1],
                           [1.1, 11.1, 111.1],
                           [1.1, 11.1, 111.1],
                           [1.1, 11.1, 111.1]])

        self.assertEqual(ma.allclose(values, should_be, rtol=1e-4),
                         True, msg = "Error in " + self.variable_name)

if __name__ == "__main__":
    opus_unittest.main()


def main():
    f = open("input/day1.txt", "r")
    counter = 0
    tmp = 0
    for x in f.readlines():
        x = int(x.rstrip())
        if(x > tmp and tmp != 0):
            counter += 1
        tmp = x
    print(counter)

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""
Created on Sun May  2 10:11:50 2021

@author: Simon
"""

# Imports
import matplotlib.pyplot
import csv
from bs4 import BeautifulSoup
import requests
import particlemove # Associated file used to move particles
import tkinter as tk
import time

# Model variables
num_of_iterations = 200  # This no. allows all particles to land in high wind
num_of_particles = 0  # This creates the object it is updated in the GUI
wind_speed = 0  # This is updated in the GUI

# Creating lists
particles = [] #Used to hold particle data
citydata = [] #Used to hold bombsite and then particle landing position data
environment = [] #Used to hold a digital elevation model

# Start a timer to time the code
start = time.time() #Used for measuring how long it takes at the end

# Setting up GUI, this part of the code runs before main() at the bottom
# The overall strucutre and some elements of the GUI were developed based
# on tutorials under the name The New Boston found on You Tube (see references)

# This is the routine that runs when the user clicks the run button
def routine():
    """The function called by pressing Run in the GUI, collects user inputs"""
    global num_of_particles  # Used in other functions so made global
    num_of_particles = int(my_entry.get())
    print("The number of particles is", num_of_particles)
    global wind_speed
    wind_speed = int(scale_widget.get())
    print("The wind speed is ", wind_speed)
    global topography  # Used to select the type of surface or basemap
    topography = str(listbox_widget.get(tk.ANCHOR))
    print("The model uses a", topography)

# The functions below print help instructions when selected
def particlehelp():
    """Prints some help relating to particle numbers when requested in GUI"""
    print("HELP")
    print("The number of particles chosen will influence the speed")
    print("5000 particles will typically take about 5 seconds")
    print("If you are interested in rare events where particles land far from")
    print("the main landing area then you may want to use more particles")

def windspeedhelp():
    """Prints some help relating to windspeed when requested in the GUI"""
    print("HELP")
    print("The higher windspeed causes more turbulence")
    print("Resulting in particles being more dispersed")
    print("The wind direction is fixed as Easterly")
    print("In strong wind (above 6) the particles are blown further East")

def surfacehelp():
    """Prints some help relating to the surface choice when requested in GUI"""
    print("HELP")
    print("The basic model assumes a uniform flat surface or flat plain")
    print("The digital elevation model uses a contoured surface")
    print("The contoured surface used slopes down in an Easterly direction")
    print("This means that particles travel further using the DEM")

# Set up the GUI window and size
root = tk.Tk()
root.geometry("500x300")
root.title("Bacterial Bomb") #Add a title to the GUI window

# Add a menu with help function
# Source: https://www.youtube.com/watch?v=PSm-tq5M-Dc
menu1 = tk.Menu(root)
root.config(menu=menu1)
subMenu = tk.Menu(menu1)
menu1.add_cascade(label="Help", menu=subMenu)
subMenu.add_command(label="Particle choice", command=particlehelp)
subMenu.add_command(label="Windspeed", command=windspeedhelp)
subMenu.add_command(label= "Surface", command=surfacehelp)

# Add a button used for running the program, routine run when button clicked
button1 = tk.Button(root, text ="Run", command=routine)
button1.grid(row=6, column=0)

# Add a label above the entry box
label2 = tk.Label(root, text="Enter number of particles: 5000 recommended")
label2.grid(row=2, column=4, padx=5, pady=5)

# Add an entry box used for number of particles
my_entry = tk.Entry(root, width=15)
my_entry.grid(row=3, column=4)

# Add a label above the scale widget
label3 = tk.Label(root, text="Enter wind speed (beaufort scale)")
label3.grid(row=4, column=4)

# Add a scale widget for windspeed
# Source: dummies.com/programming/python/using-tkinter-widgets-in-python/
scale_widget = tk.Scale(root, from_=0, to=12, orient=tk.HORIZONTAL)
scale_widget.set(4)
scale_widget.grid(row=5, column=4)

# Add a label above the scale widget
label4 = tk.Label(root, text="Enter the type of surface")
label4.grid(row=7, column=4)

# Add a drop down box for choosing the type of surface
listbox_entries = ["Flat plain", "Digital elevation model"]
listbox_widget = tk.Listbox(root, height=2, width=25)
for entry in listbox_entries:
    listbox_widget.insert(tk.END, entry)
listbox_widget.grid(row=8, column=4, padx=5, pady=5)

textbox = tk.Text(root,height=4, width=20, padx=5,
                  pady=5, font=("Helvetica",10))
textbox.insert(
    tk.END,"INSTRUCTIONS\nChoose parameters\nPress Run\nClose this window\n")
textbox.grid(row=0, column=0, padx=5, pady=5)

root.mainloop()# GUI window keeps running until it is closed

# The following functions are all called in main at the bottom. They are listed
# in order that they are called.

# Scraping data from the web to identify bomb location (need to be online)
# Website address line is too long but could not make it work splitting it up
def getdata():
    """Scrapes file with the bomb site from the web and saves it as citydata"""
    city = []
    url ="http://www.geog.leeds.ac.uk/courses/computing/study/core-python-odl2/assessment2/wind.raster"
    html_content = requests.get(url).text
    soup = BeautifulSoup(html_content, "lxml")
    city = soup.find_all("p")
# Save beautiful soup resultset as text file to access the individual numbers
# Saving to a file then reading that file seems rather inefficent
# Need to find a better way to access the data using BeautifulSoup
    with open('city.txt', 'w') as testfile:
        for row in city:
            testfile.write(' '.join([str(a) for a in row]) + '\n')

# This code opens the text file and defines the reader, the new line separator
# in the dataset, and the format of the data with one decimal place.
# Code mainly copied from agent based model work.
    f = []
    f = open('city.txt', newline='\n')
    reader = csv.reader(f, quoting=csv.QUOTE_NONNUMERIC)
    for row in reader: #Fill the list with 2D data row by row
        citydata.append(row)
    del citydata[300]  # Deletes a fragment of html syntax
    f.close()
    #print(citydata[0]) #Testing prints
    #print(len(citydata))#Expecting 300 items, but gives 301
    #print(citydata[300]) #Check what is the last item to make 301
    #del citydata[300] #Deletes a fragment of html syntax
    #print(len(citydata)) #We now have a list with data for a 300x300 frame

# This code reads an environment data file to use as a DEM basemap.
# Then, if chosen, instead of landing on flat surface particles land on a DEM.
# This code is copied from agent based model work.
def getenvironment():
    """Reads a file with a contoured surface and saves it as environment"""
    file = []
    file = open('in.txt', newline='')
    reader = csv.reader(file, quoting=csv.QUOTE_NONNUMERIC)
    for row in reader:  # Fill the list with 2D data row by row
        environment.append(row)
    file.close()
# Find height of land at bomb site
# Particle assumed to be released from height of building + height of land
    #print(environment[150][50]) # Land is 200m at bomb site

# Plot the data for intial exploration
#matplotlib.pyplot.imshow(citydata)
#matplotlib.pyplot.axis([0,299,0,299])
#matplotlib.pyplot.show() # Appears to be data around x50 y150

# This code identifies the bomb site
def findbomb():
    """Indentifies the x and y coordinates of the bomb site"""
    for i in range (len(citydata)):
        for j in range (len(citydata[i])):
            if citydata[i][j]>0:
                #print(citydata[i][j])
                global xb
                global yb
                xb = j  # The coordinates of the bomb
                yb = i

# So now we know that there is a single bombsite at location x50,y150.
# It is marked by the number 255, whilst all other cells have zero

# This function creates particles used in function below
# Assume a human stands on the building to release particles 1m above roof
# If "Flat plain" is selected particle height is 75m plus 1m = 76m
# If "DEM" is selected particle height is 200m + 76m = 276m
def createparticles():
    """Creates the number of particles specified in the GUI"""
    if topography == "Digital elevation model": #Selected in GUI
        z = 276 # The elevation in the DEM at the bomb site is 200m
    else:
        z = 76

    for i in range(num_of_particles):
        x = xb
        y = yb
        ws = wind_speed
        particles.append(particlemove.Particle (x, y, z, ws, environment))
        #print(particles[i])  # Used for testing
        #print(particles[0].x)

# This function iterates the particles through methods in particlemove.py
def iterateparticles():
    """Iterates particles through the move methods in particlemove.py"""
    for j in range(num_of_iterations):
        #print("Iteration")
        for i in range(num_of_particles):
            #print("Particle moving")
            particles[i].zmove()  # Moves particles up or down
            particles[i].landing()  # Considers if the particle has landed
            particles[i].xymove()  # Moves particles x or y coordinates

        #for i in range(num_of_particles):
            #print(particles[i])

# Plot the data as a density map.
# Firstly record the number of particles in each cell of citydata
# Increment the citydata file for each particle landing
# Then plot this data as a density map
# Two mapping options based on Flat plain or DEM selection
def plotdata():
    """Records coordinates of each landing particle and plots a density map"""
    #print("Plotting data")
    for i in range(num_of_particles):
        citydata[particles[i].y][particles[i].x] += 1  # Increment per particle
    citydata[150][50] -= 255 #Set bomb site data to zero

    #for i in range(len(citydata)):
        #for j in range(len(citydata[i])):
            #if citydata[i][j]>60: #Used to examine the upper range of data
                #print("x ",i,"y ",j,"number ", citydata[i][j])

# If the user has chosen a Flat plain in the GUI the topography = Flat plain
    if topography == "Flat plain":
        #print("Flat plain")
        # Vary the max in line below to see broad range or high central points
        matplotlib.pyplot.imshow(citydata, vmin=0,vmax=40)
        matplotlib.pyplot.colorbar(label="Particles")
        matplotlib.pyplot.title("Map showing distribution of particles",
                                fontdict=None, loc=None, pad = None, y = None)
        matplotlib.pyplot.text(45, 80, s="X marks the bomb site", fontsize=7)
        matplotlib.pyplot.text(
            45, 76,s="White dots mark cells where single particles landed",
            fontsize=7)
        matplotlib.pyplot.axis([45, 200, 100, 200])
        matplotlib.pyplot.scatter(50, 150, marker="x", linewidth=3, c="w")
        # Lines below add white dots where there is a single particle
        for i in range(len(citydata)):
            for j in range(len(citydata[i])):
                if citydata[i][j] == 1:
                    matplotlib.pyplot.scatter(j, i, s=0.3, c="w")
        matplotlib.pyplot.show()

    else: #If DEM has been chosen
        #print("Digital elevation model")
        matplotlib.pyplot.contourf(environment)
        matplotlib.pyplot.colorbar(label="Elevation")
        matplotlib.pyplot.title(
            "Map showing distribution of particles",
            fontdict=None, loc=None, pad=None, y=None)
        # Next two lines are too long, splitting them mad the plot look poor
        matplotlib.pyplot.text(45, 66, s="X marks the bomb site, White dots mark cells where single particles landed",fontsize=7)
        matplotlib.pyplot.text(45, 62, s="Pink dots mark cells where 2 to 15 particles landed, Red dots mark cells where more than 15 landed",            fontsize=7)
        matplotlib.pyplot.axis([45, 300, 80, 220])
        matplotlib.pyplot.scatter(50, 150, marker="x", linewidth=3, c="w")
        # Code below creates a scatter plot showing different intensities
        for i in range(len(citydata)):
            for j in range(len(citydata[i])):
                if citydata[i][j] > 15:
                    matplotlib.pyplot.scatter(j, i, s=0.3, c="r")
                elif citydata[i][j] > 1 <16:
                    matplotlib.pyplot.scatter(j, i, s=0.3, c="tab:pink")
                elif citydata[i][j] == 1:
                    matplotlib.pyplot.scatter(j, i, s=0.3, c="w")
        matplotlib.pyplot.show()

# Save the density map to a text file (Need to eliminate decimal place)
def savedata():
    """Saves the landed particle coordinates into a text file, citydata.txt"""
    with open('citydata.txt', 'w') as testfile:
        for row in citydata:
            testfile.write(' '.join([str(a) for a in row]) + '\n')

# This is the main function that organises and calls the other functions
def main():
    """Runs the main functions and times the code"""
    mainstart = time.time()  #For timing the main program
    getdata()
    findbomb()
    getenvironment()
    createparticles()
    iterateparticles()
    plotdata()
    savedata()
    mainend = time.time()
    time_elapsed = mainend-mainstart
    print("TIMING")
    print ("Time elapsed", "%.4f" % time_elapsed,"seconds")
    print("End, file saved to citydata.txt")

main()


from django.db import models
from django.conf import settings

from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync

import uuid

channel_layer = get_channel_layer()

class MessageManager(models.Manager):
    def get_pending_messages(self, user):
        pending_messages_qs = user.pending_messages.order_by('timestamp')
        for message in pending_messages_qs:
            message.remove_user_from_pending(user)
        return pending_messages_qs

    def mark_room_as_read(self, user, room):
        unread_messages_qs = user.unread_messages.filter(room=room)
        for message in unread_messages_qs:
            message.mark_as_read(user)
        return unread_messages_qs

class Message(models.Model):
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE)
    room = models.ForeignKey(
        'Room',
        related_name='messages',
        on_delete=models.CASCADE)
    body = models.TextField(max_length=500, default='')
    timestamp = models.DateTimeField(auto_now_add=True)

    pending_reception = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='pending_messages')

    pending_read = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='unread_messages')

    front_key = models.UUIDField(
        verbose_name="frontend key",
        default=uuid.uuid4,
        unique=True)

    objects = MessageManager()

    class Meta:
        verbose_name = "Mensaje"
        verbose_name_plural = "Mensajes"

    def __str__(self):
        return self.body

    def signal_to_room(self, message, data={}):
        for participant in self.room.participants.all():
            async_to_sync(channel_layer.group_send)(
                f"group_general_user_{participant.id}", {
                    "type": "chat_message",
                    "message": message,
                    'data': data
                })

    def remove_user_from_pending(self, user):
        if self.pending_reception.filter(id=user.id).exists():
            self.pending_reception.remove(user)
            # If there are no more pending then signal
            if not self.pending_reception.exists():
                self.signal_to_room('update_message', {
                    'message_id': self.id,
                    'kind': 'all_received'
                })

    def mark_as_read(self, user):
        if self.pending_read.filter(id=user.id).exists():
            self.pending_read.remove(user)
            # If there are no more pending then signal
            if not self.pending_read.exists():
                self.signal_to_room('update_message', {
                    'message_id': self.id,
                    'kind': 'all_read'
                })

class Room(models.Model):
    class RoomKind(models.IntegerChoices):
        PRIVATE = 1
        GROUP = 2

    group_name = models.CharField(max_length=255, blank=True, null=True)
    kind = models.IntegerField(choices=RoomKind.choices)
    participants = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='rooms')

    created_at = models.DateTimeField(
        verbose_name='Creation Date',
        auto_now_add=True)
    last_activity = models.DateTimeField(
        verbose_name='Last activity date',
        auto_now=True)

    class Meta:
        verbose_name = "Sala"
        verbose_name_plural = "Salas"

    def signal_to_room(self, message, data={}):
        for participant in self.participants.all():
            async_to_sync(channel_layer.group_send)(
                f"group_general_user_{participant.id}", {
                    "type": "chat_message",
                    "message": message,
                    'data': data
                })


import sys
import os
import time
import traceback
import numpy as np

import torch
import torchvision
import torch.nn as nn
import torch.nn.init as init
import torch.optim as optim
import torch.nn.functional as F
import torchvision.transforms as transforms
from torch.autograd import Variable

from tqdm import tqdm
#conda install tqdm
from collections import OrderedDict

sys.path.append('../')

from SOL4Py.torch.ZTorchModel    import ZTorchModel
from SOL4Py.torch.ZTorchEpochChangeNotifier    import ZTorchEpochChangeNotifier
from SOL4Py.torch.ZTorchModelCheckPoint    import ZTorchModelCheckPoint

##
# ZTorchSimpleModel

class ZTorchSimpleModel(ZTorchModel):
  #
  # Constructor
  def __init__(self, image_size, n_classes, model_filename):
    super(ZTorchSimpleModel, self).__init__(image_size, n_classes, model_filename)
    self.n_classes      = n_classes
    self.image_size     = image_size;
    ch, h, w            = image_size
    print("ch:{} h:{} w:{}".format(ch, h, w))
    self.model_filename = model_filename

    # The following is based on AlexNet
    self.features = nn.Sequential(

        nn.Conv2d(ch, 64, kernel_size=3, padding=1),
        nn.ReLU(inplace=True),
        nn.MaxPool2d(kernel_size=2, stride=2),

        nn.Conv2d(64, 192, kernel_size=5, padding=2),
        nn.ReLU(inplace=True),
        nn.MaxPool2d(kernel_size=2, stride=2),

        nn.Conv2d(192, 384, kernel_size=3, padding=1),
        nn.ReLU(inplace=True),

        #nn.Conv2d(384, 256, kernel_size=3, padding=1),
        nn.Conv2d(384, h, kernel_size=3, padding=1),

        nn.ReLU(inplace=True),

        nn.Conv2d(h, h, kernel_size=3, padding=1),
        nn.ReLU(inplace=True),
        nn.MaxPool2d(kernel_size=2, stride=2),
        )

    self.n_features = 256 * 4 * 4

    if h == 32:
      self.n_features = h * 4 * 4  # 512
    if h == 64:
      self.n_features = h * 8 * 8  # 4096

    if h == 96:
      self.n_features = h * 9216   # 884736

    if h == 128:
      self.n_features = h * h * h  #  2097152

    self.classifier = nn.Sequential(
        nn.Dropout(),
        nn.Linear(self.n_features, self.n_features),

        nn.ReLU(inplace=True),
        nn.Dropout(),
        nn.Linear(self.n_features, self.n_features),
        nn.ReLU(inplace=True),
        nn.Linear(self.n_features, n_classes)
        )

  def forward(self, input):
    output = self.features(input)
    output = output.view(output.size(0), self.n_features)
    output = self.classifier(output)
    return output