# -*- coding: utf-8 -*-
'''
Created on 2020.

@author: aon
'''
from api.formTools import _tab, style, _div, _field, label, _btnD, _table, _span, labField, _br, labell, labelc, _teg
from api.classPage import Page

# *** *** ***

class a_setting(Page):
    delay = 1000

    def __init__(self, form):
        self.title = 'Setting'
        self.jsCssUrl = ['jsv?api/pages/a_setting/a_setting.js',
                         'jsv?api/pages/a_setting/table.js',
                         'jsv?api/pages/a_setting/table.css'
                        ]
        self.dbAlias = 'db_pages_2'
        super().__init__(form)

    def page(self, dcUK):
        self.d3 = dcUK.key
        return _div(className='setting-page', children=[
            _div(name='setPage', children=self.settingPage()),
            _div(name='setBox', children=self.settingDiv()),
        ])

    def queryOpen(self, dcUK):
        pass

# *** *** ***

    def settingPage(self):
        if self.d3:
            screen = _field('screen', 'band', [
                _div(className='tb-pc', children=[
                    _div(className='tb-pc-screen'),
                    _div(className='tb-pc-ground',
                        children=[
                            _div(**style(width='35%', borderBottomRightRadius=7)),
                            _div(**style(width='30%', background='#888')),
                            _div(**style(width='35%', borderBottomLeftRadius=7))
                        ]),
                ]),
                _div(className='tb-phone'),
            ], className='screens')
        else:
            screen = _field('screen', 'band', [
                _div(className='tb-phone'),
                _div(className='tb-tablet'),
                _div(className='tb-pc', children=[
                    _div(className='tb-pc-screen'),
                    _div(className='tb-pc-ground',
                        children=[
                            _div(**style(width='35%', borderBottomRightRadius=7)),
                            _div(**style(width='30%', background='#888')),
                            _div(**style(width='35%', borderBottomLeftRadius=7))
                        ]),
                ]),
            ], className='screens')

        body = [
           screen,

            _div(className='setting-line'),
            _div(wl=50, **style(width=255), children=_table(
                    labField('проект', 'project'),
                    labField('имя', 'pageName'),
                    labField('url', 'pageUrl'),
                    labField('title', 'title'),
                    # labField('js', 'script'),
                    # labField('css', 'css'),
                    labField('notes', 'notes'),
                    labField('key', 'key', 'lbsd', ['Помещения|rooms', 'Мебель|cases', 'Стены|walls', 'Дом|home', '2d html|html', 'Архив|Archive'], alias=1, small='2'),
                )
            ),
            _div(className='setting-line'),
            _div(**style(width=255, paddingBottom=5), children=_table([
                _field('phoneContur', 'chb', ['контур'], className='labelc'),
                # _field('pagePlusPreview', 'chb', ['preview'], className='labelc')
                ])
            ),

            # not self.d3 and _div(className='setting-line'),
            # not self.d3 and _div(**style(width=270), children=_table([
                # _field('pagePlusDim', 'slip', [1, 5, 0.5, 'Mасштаб'], digits=2, className='label'),
                # _div(''),
                # ])
            # ),

            # not self.d3 and _div(className='setting-line'),
            # not self.d3 and _field('table', 'chb', ['таблица'], **style(margin=10, textAlign='center')),
            # not self.d3 and _div(name='isTable', children=[
    # #            _tab(30, [ self.tabItem(i) for i in range(1, 10) ]),
                # _field('tableSize', 'slip', [0, 9, 1, 'число закладок'], className='label', **style(display='block', margin='10px auto', width=200)),
                # _btnD('создать', 'crtTable', **style(margin='10px auto', width=100))
            # ]),
        ]

        # ***

        return [
        _div(**style(textAlign='center'), children=[_field('docNo_FD', 'fd', className='h3')]),
        _div(className='setting-line'),

        *body,

        _div(className='setting-line'),

        _div(wl=75, **style(width=255, marginBottom=5), children=_table(
            labField('создан', 'created_FD', 'fd', className='tta', **style(display='table-cell')),
            labField('автор', 'creator_FD', 'fd', className='tta', **style(display='table-cell')),
            labField('изменен', 'modified_FD', 'fd', className='tta', **style(display='table-cell')),
            labField('редактор', 'modifier_FD', 'fd', className='tta', **style(display='table-cell')),
            labField('закрыт' , 'closed', 'dt') if self.d3 else
            labField('опубликован', 'published', 'dt'),
            )
        ),
    ]

    # *** *** ***

    # def tabItem(self, i):
        # f = _div(**style(padding=10), children=[
            # _field(f'tabBtn_{i}', 'chb', ['добавить заголовок']), _field(f'tab_{i}')])
        # return f'T{i}', f

    # *** *** ***

    def settingDiv(self):

        return [

         # типы стрелок
        _div(name='arrow', id='arrow', children=self.arrow()),

        # общие поля rooms
        _div(name='is3d0', **style(background='#ffd8d8'),
            children=self.is3d0()),

        # свойства rooms: ширина, длина, высота, Толщина стен
        _div(name='is3d1',
            children=self.is3d1()),

        # свойства стены
        _div(name='walls',
            children=self.is3wall1()),

        # таблица внутри 3д-блока
        _div(name='m3tab', **style(background='#f7d98b'), children=self.m3tab()),

        # общие поля одиноких стен и кирпичей: bb3d2, поворот , наклон
        _div(name='mmmNotRooms', **style(background='#f7d98b'), children=self.mmmNotRooms()),

        # свойства одинокого блокa
        _div(name='bricksOne', children=self.bricksOne()),
        _div(name='bricksEdge', children=self.bricksEdge()),

        # свойства блокa в стене
        _div(name='bricksM3t', children=self.bricksM3t()),

        # свойства box: bb, масштаб, см/мм, создать 3д
        _div(name='bb', children=self.box2d0()),

        # свойства 3d-rooms: показать потолок, пер-ва, cm/mm, угол скрытия etc
        _div(name='is3d1',
            children=self.is3d2()),

        # свойства стены
        _div(name='walls',
            children=self.is3wall2()),

        # мебель
        _div(name='furniture',
            children=self.furniture()),

        # fixes, lineOff, insideOff
        _div(name='is3d4', **style(background='#ffd8d8'),
            children=self.is3d4()),

        _div(name='tumba', className='tumba',
            children=self.tumba()),

        # все свойства бокса, кроме фона
        _div(name='bb', children=self.box2d1())
    ]
    # *** *** ***

    # bb3d, поворот 3d, наклон 3d
    def is3d0(self):
        return [
            _field('bb3d', 'band', ['\xa03d \xa0', 'стены', 'мебель', 'эл-ка'],
                **style(fontSize=14, color='#048', borderSpacing='4px')
            ),

            *_table([
                _field('rotate3Z', 'slip', [-360, 360, 15, 'поворот'], className='label'),
                _field('rotate3X', 'slip', [-90, 90, 15, 'наклон'], className='label'),
            ]),

            _div(name='wedWall', **style(padding='3px 0'), children=[
                _div(className='setting-line', **style(margin='3px 0 0 0')),
                labelc('Показать'),
                _field('wedWall', 'chb3', ['\xa0\xa0Все стены\xa0|wed1', 'Только одну|wed2'], noEmpty=1, **style(margin='0 auto')),
            ]),

            _div(className='setting-line'),
            _div(className='setting-head', children=[
                _span('Масштаб', className='setting-title'),
                _field('hide33', 'chb', ['▼', '►'], title='сложить/показать', char=1, **style(float='right')),
            ]),
            _field('scale3d', 'slip', [0.05, 2, 0.05, ' ', 10], name='hide33', digits=2, className='label', **style(margin='0 auto 7px'), delay=self.delay),
            _field('cm', 'chb3', ['размер в см|cm', 'размер в мм|mm'], name='hide33', noEmpty=1, **style(margin='0 auto')),

            # фасад/грани для стены
            _div(name='wall_wed', **style(paddingBottom=3, background='#ffe39c'), children=[
                    _div(className='setting-line', **style(margin='0px 0 0 0')),
                    labelc('Редактировать 3d блок (is3d0)'),
                    _field('wall_wed', 'band', ['таблица', 'фасад', 'грани'], **style(margin='0 auto')),
              ]),
        ]

    # *** *** ***

    # Размеры, наклон стен
    def is3d1(self):
        return [
            _div(className='setting-line'),

            _div(children=_table(
                [
                    labelc('ширина'), labelc('длина'), labelc('высота')
                ],
                [
                    style('rowStyle', border=0, padding=0, margin=0),
                    _field('is3dX', 'number', max=100000, digits=1, width=70, className='label labelc', delay=self.delay),
                    _field('is3dY', 'number', max=100000, digits=1, width=70, className='label labelc', delay=self.delay),
                    _field('is3dZ', 'number', max=100000, digits=1, width=70, className='label labelc', delay=self.delay)
                ]
            )),
            _div(children=_table([
                label('Толщина стен', **style(verticalAlign='middle')),
                _field('w3', 'number', max=100000, digits=1, width=50, className='label labelc'),
                 label(' ')
            ])),
        ]

    def is3d2(self):
        return [
            # показать потолок
            _div(className='setting-line'),
            _div(**style(width=180, margin='auto', border='0 solid #555', borderBottomWidth=1),
                children=[_field('coverOn', 'chb', ['показать потолок'])
            ]),

            # перспектива
            _div(children=[
                _field('persOn', 'chb', ['перспектива'], **style(margin=3, textAlign='center')),
                _div(name='perspective', children=_table(
                    [
                        _field('perspectiveOriginX', 'slip', [0, 100, 1, 'X'], className='label'),
                        _field('perspectiveOriginY', 'slip', [0, 100, 1, 'Y'], className='label'),
                    ],
                    [
                        _field('perspective', 'slip', [100, 5000, 100, 'Z'], className='label'),
                    ]
                )),
            ]),
            _div(className='setting-line'),

            # размер в см|mm

            * _table([
                _field('angleHide', 'slip', [0, 90, 5, 'угол скрытия стен'], className='label labelc'),
                _div(' ', **style(width=10, border='0px solid #888', borderRightWidth=1)),
                _field('sweep', 'slip', [0, 90, 5, 'угол наклона стен'], className='label labelc'),
            ]),

            #  копировать удалить
            _div(className='setting-line'),
            _div(children=_table([
                    _btnD('Копировать', 'copy3d'),
                    _btnD('Удалить 3d', 'del3d', className='rsvTop armBtnRed'),
                ], **style('rowStyle', borderSpacing='8px 0'))
            ),

            # тень для 3д
            _div(className='setting-head', children=[
                _span('Тень', className='setting-title'),
                _field('hide31', 'chb', ['▼', '►'], title='сложить/показать', char=1, **style(float='right')),
            ]),

            _div(name='shadow3', children=[
                _div(className='setting-line'),
                *_table([
                    _div(**style(width='20%', textAlign='center'), children=[
                        _span('Цвет', **style(textAlign='center', font='bold 9pt Verdana, Arial', color='#048')),
                        _field('shadowColor3', 'input-color', colorList='rainbow')
                    ]),
                    _div(**style(paddingLeft=10, textAlign='center', borderLeftWidth=1, border='0 solid #aaa'), children=[
                        _field('shadowW3', 'slip', [0, 200, 1, 'ширина', 2000], **style(display='block')),
                        _field('shadowR3', 'slip', [0, 200, 1, 'размытие', 2000], **style(display='block')),
                        _br(),
                    ]),
                ]),
            ]),
        ]

    # *** *** ***

    def is3d4(self):
        return [
            _div(className='setting-line'),
            *_table([
                _field('mmm_fixed', 'chb', ['не двигать'], title='запретить двигать мышкой 3d блок'),
                _field('turnOn', 'chb', ['вращать']),
            ],
            [_div('', **style(height=5))],
            [
                _field('lineOff', 'chb', ['скрыть\xa0размер'], title='не показывать линии с размерами'),
                _field('insideOff', 'chb', ['скрыть\xa0мебель'], title='не показывать линии с размерами'),
            ]),
            _div(className='setting-line'),
        ]

    # *** *** ***

    def m3tab(self):
        return [
            labelc('Редактировать 3d блок (m3tab)'),
            _field('m3tab_wed', 'band', ['таблица', 'фасад', 'грани'], **style(margin='0 auto 5px')),

            # _div(className='setting-line', **style(margin=0)),
            # *_table(
            #     [ labelc('ширина'), labelc('высота'), labelc('глубина') ],
            #     [
            #         style('rowStyle', border=0, padding=0, margin=0),
            #         _field('m3tab_is3dX', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
            #         _field('m3tab_is3dY', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
            #         _field('m3tab_is3dZ', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
            #     ],
            # ),
            # _div(className='setting-line', **style(margin=3)),
        ]

    # *** *** ***

    def mmmNotRooms(self):
            return [
            *_table([
                _field('m3table_rotate3Y', 'slip', [-360, 360, 15, 'поворот'], className='label'),
                _field('m3table_rotate3X', 'slip', [-90, 90, 15, 'наклон'], className='label'),
            ]),

            _div(className='setting-line'),

            _div(className='setting-head', children=[
                _span('Масштаб', className='setting-title'),
                _field('m3table_hide33', 'chb', ['▼', '►'], title='сложить/показать', char=1, **style(float='right')),
            ]),
            _field('m3table_scale3d', 'slip', [0.05, 2, 0.05, ' ', 10], name='m3table_hide33', digits=2, className='label', **style(margin='0 auto 7px')),
            _field('m3table_cm', 'chb3', ['размер в см|cm', 'размер в мм|mm'], name='m3table_hide33', noEmpty=1, **style(margin='0 auto')),

            _div(className='setting-line'),

            labelc('Редактировать 3d блок (mmmNotRooms)'),
            _field('m3table_wed', 'band', ['таблица', 'фасад', 'грани'], **style(margin='0 auto 5px')),

            _div(className='setting-line', **style(margin=0), name='mmmNotRooms2', children=
                _table(
                    [ labelc('ширина'), labelc('высота'), labelc('глубина') ],
                    [
                        style('rowStyle', border=0, padding=0, margin=0),
                        _field('m3table_is3dX', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
                        _field('m3table_is3dY', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
                        _field('m3table_is3dZ', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
                    ],
                ),
            ),

            #  копировать удалить
            _div(name='copyDel3d2', children=[
                _div(className='setting-line'),
                _div(children=_table([
                        _btnD('Копировать', 'copy3d2'),
                        _btnD('Удалить 3d', 'del3d2', className='rsvTop armBtnRed'),
                    ], **style('rowStyle', borderSpacing='8px 0'))
                ),
            ]),

            _div(className='setting-line'),
            *_table(
                [
                _field('m3table_fixed', 'chb', ['не двигать'], title='запретить двигать мышкой 3d блок'),
                _field('m3table_turnOn', 'chb', ['вращать']),
                ],
                [
                _field('m3table_insideOnly', 'chb', ['привязать'], title='запретить 3d блоку выходить за грницы родителя'),
                _field('m3table_turnOnQQ', 'chb', [' '], title=''),
                ]
            ),
            _div(className='setting-line'),
        ]
    #
    # def m3tableInside(self):
    #         return [
    #
    #         _div(className='setting-line'),
    #
    #         labelc('Редактировать 3d блок'),
    #         _field('mi_wed', 'band', ['таблица', 'фасад', 'грани'], **style(margin='0 auto 5px')),
    #
    #         _div(className='setting-line', **style(margin=0), name='mmmNotRooms2', children=
    #             _table(
    #                 [ labelc('ширина'), labelc('высота'), labelc('глубина') ],
    #                 [
    #                     style('rowStyle', border=0, padding=0, margin=0),
    #                     _field('mi_is3dX', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
    #                     _field('mi_is3dY', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
    #                     _field('mi_is3dZ', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
    #                 ],
    #             ),
    #         ),
    #
    #         #  копировать удалить
    #         # _div(name='copyDel3d2', children=[
    #         #     _div(className='setting-line'),
    #         #     _div(children=_table([
    #         #             _btnD('Копировать', 'copy3d2'),
    #         #             _btnD('Удалить 3d', 'del3d2', className='rsvTop armBtnRed'),
    #         #         ], **style('rowStyle', borderSpacing='8px 0'))
    #         #     ),
    #         # ]),
    #
    #         _div(className='setting-line'),
    #         _field('mi_insideOnly', 'chb', ['привязать'], **style(textAlign='center'), title='запретить 3d блоку выходить за грницы родителя'),
    #
    #     ]
    #
    #

    # *** *** ***

    def bricksEdge(self):
        return [
            labelc('Редактировать (bricksEdge)'),
            _div(children=[
                _field('brickEdge_wed', 'band', ['фасад', 'грани'], **style(margin='0 auto 5px'))
            ]),
        ]

    def bricksOne(self):
        return [
            _div(**style(paddingTop=5, textAlign='center'), name='bricksOne2', children=[
                _span('Масштаб', className='setting-title'),
                _field('brick_hide35', 'chb', ['▼', '►'], title='сложить/показать', char=1, **style(float='right')),

                _field('brick_scale3d', 'slip', [0.05, 2, 0.05, ' ', 10], name='brick_hide35', digits=2, className='label', **style(margin='0 auto 7px')),
                _field('brick_cm', 'chb3', ['размер в см|cm', 'размер в мм|mm'], name='brick_hide35', noEmpty=1, **style(margin='0 auto')),

                _div(className='setting-line'),
            ]),

            _div(name='bricksOne4', children=[
                labelc('Редактировать (bricksOne)'),
                _div(children=[
                    _field('brick_wed', 'band', ['фасад', 'грани'], **style(margin='0 auto 5px'))
                    ]),
            ]),

            _div(className='setting-line', **style(margin=0)),
            *_table(
                [ labelc('ширина'), labelc('высота'), labelc('глубина') ],
                [
                    style('rowStyle', border=0, padding=0, margin=0),
                    _field('brick_is3dX', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
                    _field('brick_is3dY', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
                    _field('brick_is3dZ', 'number', max=100000, digits=1, width=70, className='labelc', delay=self.delay),
                ],
            ),

            _div(className='setting-line'),

            _field('brick_rotate3X', 'slip', [-360, 360, 1, 'наклон блока'], className='label', digits=1),
            _field('brick_rotate3Y', 'slip', [-360, 360, 1, 'поворот блока'], className='label', digits=1),
            _field('brick_rotate3Z', 'slip', [-360, 360, 1, 'поворот блока Z'], className='label', digits=1),

            _div(className='setting-line'),
            _div('сдвиг', className='label labelc_', **style(width=70, margin='auto')),
            _div(children=_table(
                    [
                        labelc('лев/прав'), labelc('верх/низ'), labelc('туда/сюда')
                    ],
                    [
                _field('brick_left', 'slip', [-10000, 10000, 1, '', 100000, -100000], className='label'),
                _field('brick_top', 'slip', [-10000, 10000, 1, '', 100000, -100000], className='label'),
                _field('brick_translateZ', 'slip', [-10000, 10000, 1, '', 100000, -100000], className='label'),
                ]
            )),

            #  копировать удалить
            _div(className='setting-line'),

            _field('brick2_insideOnly', 'chb', ['привязать'], name='bricksOne3', **style(textAlign='center'), title='запретить 3d блоку выходить за грницы родителя'),

            _div(name='bricksOne2', children=[
                _div(children=_table([
                        _btnD('Копировать', 'copy3d2'),
                        _btnD('Удалить 3d', 'del3d2', className='rsvTop armBtnRed'),
                    ], **style('rowStyle', borderSpacing='8px 0'))
                ),
                _div(className='setting-line'),
                *_table(
                    [
                    _field('brick_fixed', 'chb', ['не двигать'], title='запретить двигать мышкой 3d блок'),
                    _field('brick_turnOn', 'chb', ['вращать']),
                    ],
                    [
                    _field('brick_insideOnly', 'chb', ['привязать'], title='запретить 3d блоку выходить за грницы родителя'),
                    _field('brick_turnOnQQ', 'chb', [' '], title=''),
                    ]
                ),
            ]),

            _div(className='setting-line'),
        ]

    def bricksM3t(self):
        return [
            _div(className='setting-line', **style(margin=0)),
            *_table(
                [
                    labelc('ширина', name='m3t_is3dX'),
                    labelc('высота', name='m3t_is3dY'),
                    _div(**style(width=60)),
                    labelc('глубина', name='m3t_is3dZ')
                ],
                [
                    _field('m3t_is3dX', 'number', max=100000, digits=1, width=70, name='m3t_is3dX', className='labelc', delay=self.delay),
                    _field('m3t_is3dY', 'number', max=100000, digits=1, width=70, name='m3t_is3dY', className='labelc', delay=self.delay),

                    _field('m3t_metric', 'chb', ['%', 'px'], **style(width=15), name='m3t_is3dZ', title='переключить', char=1, className='metric'),
                    _div(**style(width=30)),
                    _field('m3t_is3dZ', 'number', max=100000, digits=1, width=70, name='m3t_is3dZ', className='labelc', delay=self.delay),
                ],
            ),
            _field('m3t_fixedSize', 'chb', ['не менять размер'], name='m3t_fixed', title='зафиксировать размер ячейки', **style(marginLeft=5)),

            _div(className='setting-line'),

            _field('m3t_rotate3X', 'slip', [-90, 90, 1, 'наклон блока'], className='label'),
            _field('m3t_rotate3Y', 'slip', [-90, 90, 1, 'поворот блока'], className='label'),
            _field('m3t_rotate3Z', 'slip', [-90, 90, 1, 'поворот блока Z'], className='label'),

            _div(className='setting-line'),
            _div('сдвиг', className='label labelc_', **style(width=70, margin='auto')),
            _div(children=_table(
                [
                    labelc('лев/прав'), labelc('верх/низ'), labelc('туда/сюда')
                ],
                [
            _field('m3t_translateX', 'slip', [-1000, 1000, 1, '', 100000, -100000], className='label'),
            _field('m3t_translateY', 'slip', [-1000, 1000, 1, '', 100000, -100000], className='label'),
            _field('m3t_translateZ', 'slip', [-1000, 1000, 1, '', 100000, -100000], className='label'),
                ]
            )),
        ]

    def is3wall1(self):
        return [

        _div(className='setting-line', **style(margin='0 0 3px 0')),
        *_table(
            [
                label('ширина'),
                _field('w_is3dX', 'number', max=100000, digits=1, width=50, delay=self.delay),
                label('высота'),
                _field('w_is3dY', 'number', max=100000, digits=1, width=50, delay=self.delay),
            ]
        ),
        _div(className='setting-line'),

        # ***
        *_table(
            [
                label('слева'),
                _field('w_left', 'number', max=100000, digits=1, width=50, delay=self.delay),
                label('сверху'),
                _field('w_top', 'number', max=100000, digits=1, width=50, delay=self.delay),
            ]
        ),
        _div(className='setting-line'),

        # ***
        *_table(
            [
                labell(''),
                labell('толщина'),
                _field('w_is3dZ', 'number', max=100000, digits=1, width=50, delay=self.delay),
                labell(''),
        ]),
    ]
        # ***

    def is3wall2(self): return [

        # ***
        _field('w_rotateGr', 'slip', [-90, 90, 1, 'поворот пола'], className='label', name='rotGr'),
        _field('w_shiftGr', 'slip', [-1000, 1000, 1, 'сдвиг пола', 10000, -10000], className='label', name='rotGr'),

        _field('w_rotate', 'slip', [-90, 90, 1, 'поворот стены'], className='label', name='rotShift'),
        _field('w_shift', 'slip', [-1000, 1000, 1, 'сдвиг стены', 10000, -10000], className='label', name='rotShift'),
        _field('w_skewY', 'slip', [-360, 360, 15, 'наклон стены'], digits=1, className='label', name='rotShift'),

        _field('w_rotateTop1', 'slip', [-90, 90, 1, 'наклон потолка 1'], className='label', name='rshTop'),
        _field('w_rotateTop2', 'slip', [-90, 90, 1, 'наклон потолка 2'], className='label', name='rshTop'),
        _field('w_shiftTop', 'slip', [-1000, 1000, 1, 'сдвиг потолка', 10000, -10000], className='label', name='rshTop'),

        # *** кнопки 'окно' дверь
        _div(name='winDoor', children=[
            _div(className='setting-line'),
            * _table(
                [
                    # label('', 40),
                    _btnD('окно/дверь', 'winDoor', 'www', className='rsvTop'),
                    label('', 5),
                    _btnD('добавить\xa0стену', 'addWall', className='rsvTop'),
                    # label('', 40)
            ]),
        ]),
    ]
    # ***

    def furniture(self):

        def buttons(add, whence):
            return [
                _div(f'Мебель для комнаты ({whence})', className='label labelc',
                    children=[
                        _field(f'room{add}', 'band',
                           ['мягкая', 'корпусная', 'техника'],
                           **style(border='1px solid #aaa', fontSize=14, color='#048', borderSpacing='10px'),
                           rowLength=3, recalcText=1,
                           **style('itemStyle', width=70)
                        )
                    ],
                    **style(margin='7px 3px')
                ),
                _div(f'Мебель для кухни ({whence})', className='label labelc',
                    children=[
                        _field(f'kitchen{add}', 'band',
                           ['напольная', 'навесная', 'техника'],
                           **style(border='1px solid #aaa', fontSize=14, color='#048', borderSpacing='10px'),
                           rowLength=3, recalcText=1,
                           **style('itemStyle', width=70)
                        )
                    ],
                    **style(margin='7px 3px')
                ),
            ]

        return [

            _tab(130, [
                ['Home', _div(**style(overflow='auto'),
                    className='insideHome', children=buttons('', 'локально'))],
                ['Sova.online', _div(**style(overflow='auto'),
                    className='insideSova', children=buttons('S', 'с сервера'))],
            ]),

            # Вставить 3d в 3d можно только в режиме "мебель", если clip.boxClipboard() === '3d'
            _btnD('Вставить 3d', 'paste3d', name='paste3d', **style(width='90%', margin='7px auto')),
        ]

    # *** *** ***

    def arrow(self):

        d = 48

        return [
            _field('arrowType', 'band', [
                    _div(**style(width=d, height=d, padding='3px 0'), children=[
                        _div(**style(width=d, height=d - 6, backgroundSize='100% 100%', background='url(/images/arrHor.jpg)')),
                    ]),
                    _div(**style(width=d, height=d, padding='0 3px'), children=[
                        _div(**style(height=d, backgroundSize='100% 100%', background='url(/images/arrVer.jpg)')),
                    ]),
                    _div(**style(width=d, height=d, padding='3px 0'), children=[
                        _div(**style(width=d, height=d - 6, backgroundSize='100% 100%', background='url(/images/arr3.jpg)')),
                    ]),
                    _div(**style(width=d, height=d, padding='0 3px'), children=[
                        _div(**style(height=d, backgroundSize='100% 100%', background='url(/images/arr4.jpg)')),
                    ]),
                    _div(**style(width=d, height=d, padding=3), children=[
                        _div(**style(height=d - 6, backgroundSize='100% 100%', background='url(/images/arrVH.jpg)')),
                    ]),
                ],
                    **style('itemStyle', padding=0),
                    **style(width='auto', margin='auto', borderSpacing=7)
            ),

            _div(className='setting-line'),
            _div(**style(width='90%'), children=_table(
                [
                    label('X1'),
                    _field('x1', 'number', max=100000, width=60),
                    label('X2'),
                    _field('x2', 'number', max=100000, width=60),
                ]
            )), _div(**style(width='90%', padding='5px 0'), children=_table(
                [
                    label('Y1'),
                    _field('y1', 'number', max=100000, width=60),
                    label('Y2'),
                    _field('y2', 'number', max=100000, width=60),
                ]
            )),
            _div(**style(width=120, margin='auto'), children=_table(
                labField('длина', 'len', 'number', digits=1, readOnly=1, width=60),
            )),
            _div(className='setting-line'),
            _field('io', 'chb', ['не выходить за границы блока|1']),  # insideOnly
            _field('linked', 'chb', ['привязать к размерам блока|1']),  # insideOnly
            _btnD('удалить линию', 'deleteLine', className='rsvTop armBtnRed', **style(margin=7)),
        ]

    # *** *** ***

    def tumba(self):
        return [
            *_table([
                _div(className='btn_90', **style(borderLeftWidth=0), children=[
                    labelc('слева'),
                    _field('f_left', 'number', max=100000, digits=1, width=50),
                ]),

                _field('f_rotate3Y', 'slip', [-180, 180, 30, 'поворот'], name='ground', **style(width=160), className='label'),

                # _div('Навесная мебель', name='noGround', **style(paddingTop=10, width=160), className='labelc'),

                _div(name='noGround', className='btn_90', children=[
                    labelc('от пола'),
                    _field('f_bottom', 'number', max=100000, digits=1, width=50),
                ]),

                _div(className='btn_90', children=[
                    labelc('сверху'),
                    _field('f_top', 'number', max=100000, digits=1, width=50),
                ]),
            ]),

            _div(className='setting-line'),
            *_table([
                _field('f_fixed', 'chb', ['не двигать'], title='запретить двигать мышкой 3d блок'),
                _field('f_insideOnly', 'chb', ['привязать'], title='привязать к границам стены'),
                ],
                [_div('', **style(height=5))],
                [
                    _field('f_lineOff', 'chb', ['скрыть размер'], title='скрыть'),
                    _field('f_hide', 'chb', ['скрыть'], title='скрыть'),
                ],
                [_div('', **style(height=5))],
                [_div(className='setting-line')],
            ),
            *_table([
                _div(className='btn_90', **style(borderLeftWidth=0, width='33%'), children=[
                    labelc('ширина'),
                    _field('tumba_is3dX', 'number', max=100000, digits=1, width=50, delay=self.delay),
                ]),

                _div(className='btn_90', **style(borderLeftWidth=0, width='34%'), children=[
                    labelc('глубина'),
                    _field('tumba_is3dZ', 'number', max=100000, digits=1, width=50, delay=self.delay),
                ]),

                _div(className='btn_90', **style(borderLeftWidth=0, width='33%'), children=[
                    labelc('высота'),
                    _field('tumba_is3dY', 'number', max=100000, digits=1, width=50, delay=self.delay),
                ]),
            ]),

            _div(className='setting-line'),
            *_table([
                _div(className='btn_f_delete3d', children=[_btnD('копировать', 'f_copy3d', className='btn_f_gray')]),
                _div(className='btn_f_delete3d', children=[_btnD('удалить', 'f_delete3d')]),
            ]),
        ]

    # *** *** ***

    def box2d0(self):
        return [
            _field('bb', 'band', ['\xa0\xa0\xa0', 'бокс', 'бордюр', 'тень', 'html'],
                **style(fontSize=14, color='#048', borderSpacing='4px')),
            _div(name='scale2d', className='setting-line'),
            _field('scale2d', 'slip', [0.05, 3, 0.05, 'масштаб', 10], name='scale2d', digits=2, className='label'),
            _field('cm2d', 'chb3', ['размер в см|cm', 'размер в мм|mm'], name='scale2d', noEmpty=1, **style(margin='10px auto')),
            _div(className='setting-line', name='make3d'),
            _btnD('создать 3d', 'make3d', name='make3d', className='rsvTop armBtnRed', **style(width=150, margin='0 auto 5px')),
        ]

    def box2d1(self):
        return [
            _div(name='boxStyle', children=self.boxStyle(), className='setting-block'),

            # ***

            _div(className='setting-head', name='borders', children=[
                _span('Границы', className='setting-title'),
                _field('border', 'chb3', ['равны|borEQ', 'не равны|borNE'], **style(width='100%', margin='5px auto')),
                *self.borderStyle(),
            ]),

            # ***

            _div(name='boxContent', className='setting-head', children=[
                _span('Бокс контент', className='setting-title'),
                _field('boxContent', 'band',
                    ['\xa0\xa0\xa0\xa0', 'текст', 'редактор', 'кнопка'],  # , 'поле\xa0БД', 'SVG', 'виджет', ''],
                    rowLength=4)
            ]),

            _div(name='isField', **style(background='#def'), children=[
                labell('Имя поля'),
                _field('fieldName', 'tx'),
                labell('Тип'),
                _field('fieldType', 'lbsd', [
                    'нередактируемый текст|fd',
                    'текст|tx',
                    'дата|dt',
                    'список (один из)|lbsd',
                    'список (multivalue)|lbmd',
                    'список + текст|lbme',
                    'файлшоу|fileShow',
                ], alias=1, small='2'),
                labell('Выпадающий список', name='dropList'),
                _field('dropList', 'tx', name='dropList'),
                labell('Стиль'),
                _field('fieldStyle', 'chb3', ['стандартный|0', 'настроить|1'], **style(width='100%', margin='5px auto')),
                _teg('hr', color='#00f', size=3)
            ]),

            # стиль текста
            _div(name='textStyle', children=self.textStyle(), className='setting-block'),

            # *** Тень
            _div(name='shadow', className='setting-head', children=[
                _span('Тень', className='setting-title'),
                _field('shadow', 'chb3', ['снаружи|outside', 'внутри|inset'], **style(width='100%', margin='5px auto')),
                self.shadow(),
            ]),
        ]

    # *** *** ***

    def borderStyle(self):
        return [
            _div(name='borEQ', className='setting-block', children=[
                *self.brdStyle('')
            ]),

            _div(name='borNE', className='setting-block', children=[
                _field('borderSide', 'band', ['слева', 'сверху', 'справа', 'снизу'],
                    **style(fontSize=14, color='#048', borderSpacing='5px')),

                *self.brdStyle('Left'),
                *self.brdStyle('Top'),
                *self.brdStyle('Right'),
                *self.brdStyle('Bottom'),
            ])
        ]

    rLabel = {'': 'Радиус', 'Left': 'R(лев-ниж)', 'Top': 'R(лев-вер)', 'Right': 'R(пр-вер)', 'Bottom': 'R(пр-ниж)'}

    def brdStyle(self, side):
        return [
            *_table([
                _div(name=f'bor{side}', **style(width='22%', textAlign='center'), children=[
                    _div((side or '\xa0').lower(), **style(textAlign='center', font='bold 9pt Verdana, Arial', color='#048')),
                    _field(f'border{side}Color', 'input-color', colorList='rainbow'),
                    _div('Цвет', **style(textAlign='center', font='bold 9pt Verdana, Arial', color='#048')),
                ]),

                _div(name=f'bor{side}', **style(paddingLeft=10, fontSize=6, textAlign='center', borderLeftWidth=1, border='0 solid #aaa'),
                    children=[
                        _field(f'border{side}Width', 'slip', [0, 100, 1, 'Ширина', 10000]),
                        _field(f'border{side}Radius', 'slip', [0, 100, 5, self.rLabel[side], 10000], metric='px|%'),
                        _br(),
                ]),
            ]),
            _field(f'border{side}Style', 'band', [
                _div(**style(width=40, border='4px solid #5577cc', height=20, margin='auto')),
                _div(**style(width=40, border='4px dotted #5577cc', height=20, margin='auto')),
                _div(**style(width=40, border='4px dashed #5577cc', height=20, margin='auto')),
                _div(**style(width=40, border='4px double #5577cc', height=20, margin='auto')),
            ], name=f'bor{side}', **style(borderSpacing='5px 5px')),
        ]

    def trans(self, tr, d1, d2, step, digits=0):
        return _div(name=tr, children=_table([
                    style('rowStyle', border=0, padding=0, margin=0),
                    _field(f'{tr}X', 'slip', [d1, d2, step, 'X'], digits=digits, className='label'),
                    _field(f'{tr}Y', 'slip', [d1, d2, step, 'Y'], digits=digits, className='label'),
                    None if tr == 'skew' else _field(f'{tr}Z', 'slip', [d1, d2, step, 'Z'], digits=digits, className='label'),
                ],
            ))

    def boxStyle(self):
        return [
            _div(className='setting-head'),

            _div(name='boxSizeX', children=_table(
                [
                    label('ширина X'),
                    _field('boxSizeX', 'number', max=100000, digits=1, width=50, delay=self.delay),
                    _field('boxSizeXp', 'fd', className='label'),
                ],
            )),
            _div(name='boxSizeY', children=_table(
                [
                    label('высота Y'),
                    _field('boxSizeY', 'number', max=100000, digits=1, width=50, delay=self.delay),
                    _field('boxSizeYp', 'fd', className='label'),
                ]
            )),
            _div(className='setting-line', name='floatBox'),
            _div(name='floatBox', children=_table(
                [
                    label('отступ X'),
                    _field('rectLeft', 'number', max=100000, digits=1, width=50),
                    label('отступ Y'),
                    _field('rectTop', 'number', max=100000, digits=1, width=50),
                ]
            )),

            _div(className='setting-line'),

            _field('insideOnly', 'chb', ['привязать к родителю'], name='floatBox', title='запретить плавающему блоку выходить за грницы родителя', **style(display='block')),
            _field('fixed', 'chb', ['не двигать'], name='floatBox', title='запретить двигать мышкой плавающий блок', **style(display='block')),
            _field('noIcons', 'chb', ['скрыть иконки'], name='noIcons', **style(display='block')),
            _div(**style(padding='4px 0'), children=[
                _field('anchor', 'chb', ['якорь'], title='для перехода при клике мышкой', **style(display='inline')),
                _field('showAnchor', 'fd', name='showAnchor', **style(padding='10px 0 5px 10px', display='inline')),
            ]),

            _div(className='setting-line'),
            labell('overflow'),
            _field('overflow', 'lbsd', ['auto', 'hidden', 'scroll', 'visible', 'inherit'], small='2'),
            _div(className='setting-line'),

            _div(name='zIndex', children=
                _table([
                    _div(' '), label('z-index'),
                    _btnD('\u21D1', 'blPlus', className='metric'),
                    _field('boxLayer', 'fd', name='boxLayer', className='labelc'),
                    _btnD('\u21D3', 'blMinus', className='metric'), _div(' ')
                ])
            ),

            _div(name='zIndex', className='setting-line'),

            _div(children=[
                _field('trans', 'band', ['сдвиг', 'поворот', 'наклон']),

                self.trans('translate', -10000, 10000, 1),
                self.trans('rotate', 0, 360, 1),
                self.trans('skew', -90, 90, 15),
            ])
        ]

    def textStyle(self):

        def tx_1_2(lcr):
            return [
                _div(className='tx-1'),
                _div(className=f'tx-2-{lcr}'),
                _div(className='tx-1'),
                _div(className=f'tx-2-{lcr}'),
                _div(className='tx-1'),
            ]

        return [
            _div(className='setting-line'),
            _div(name='isButton', **style(background='#ffc6b5'), children=[
                labell('Действие'),
                _field('buttonAction', 'lbsd', ['javascript', 'Отправить данные (submit)|submit', 'url', 'перейти к якорю'], alias=1, small='2'),
                _field('buttonUrl', 'tx', name='buttonUrl'),
                _div(wl=80, name='buttonCmd', children=_table(
                    labField('Команда', 'buttonCmd'),
                    labField('Надпись', 'buttonLabel'),
                )),
                _teg('hr', color='#00f', size=3)
            ]),

            _field('textAlign', 'band', [
                _div(**style(width=30, height=30, margin='auto'), children=tx_1_2('l')),
                _div(**style(width=30, height=30, margin='auto'), children=tx_1_2('c')),
                _div(**style(width=30, height=30, margin='auto'), children=tx_1_2('q')),
                _div(**style(width=30, height=30, margin='auto'), children=tx_1_2('r')),
                ], name='textAlign', **style(width='80%', margin='auto', borderSpacing='5px')),

            labell('Шрифт'),
            _field('fontFamily', 'lbsd', ['Verdana', 'Arial', 'Courier', 'Futura PT'], small='2'),
            *_table([
                _field('fontSize', 'slip', [1, 100, 1, 'Размер', 2000], metric='rem|px', className='label', **style(width=170, paddingTop=10, marginLeft=5)),
                _div(children=[label('Цвет', **style(width=55)), _field('color', 'input-color', **style(marginLeft=20), colorList='rainbow')]),
            ]),
            *_table([
                _field('fontWeight', 'chb', ['жирный|bold'], className='label'),
                _field('fontStyle', 'chb', ['курсив|italic'], className='label')
            ]),
            _div(className='setting-line', **style(marginTop=8)),
            labelc('Интервал'),
            *_table([
                _field('letterSpacing', 'slip', [0, 50, 1, 'X', 1000], className='label', **style(width='45%'), metric='em|px'),
                _field('lineHeight', 'slip', [0, 5, 0.1, 'Y', 10], digits=2, className='label', **style(width='45%', paddingLeft=5))
            ]),
            _div(className='setting-line'),
            labelc('Отступы'),
            *_table([
                _field('paddingLR', 'slip', [0, 100, 1, 'X', 10000], className='label', **style(width='45%'), metric='em|px'),
                _field('paddingTD', 'slip', [0, 100, 1, 'Y', 10000], className='label', **style(width='45%', paddingLeft=5), metric='em|px')
            ]),
            _div(**style(margin='auto', width='90%'), children=_table(
                [_field('textIndent', 'slip', [0, 200, 1, 'Параграф', 2000], className='label', metric='em|px')])),
        ]

    def shadow(self):
        return _div(className='setting-block', name='shadowOn', children=[
            *_table([
                _div(**style(width='20%', textAlign='center'), children=[
                    _span('Цвет', **style(textAlign='center', font='bold 9pt Verdana, Arial', color='#048')),
                    _field('shadowColor', 'input-color', colorList='rainbow')
                ]),
                _div(**style(paddingLeft=10, textAlign='center', borderLeftWidth=1, border='0 solid #aaa'), children=[
                    _field('shadowW', 'slip', [0, 200, 1, 'ширина', 2000], **style(display='block')),
                    _field('shadowR', 'slip', [0, 100, 1, 'размытие', 2000], **style(display='block')),
                    _field('shadowX', 'slip', [-100, 100, 1, 'сдвиг x', 2000], **style(display='block')),
                    _field('shadowy', 'slip', [-100, 100, 1, 'сдвиг y', 2000], **style(display='block')),
                    _br(),
                ]),
            ]),
        ])

    # *** *** ***


from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
import os

# Init app
app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
# Database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'db.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Init db
db = SQLAlchemy(app)
# Init ma
ma = Marshmallow(app)

# Product Class/Model
class Product(db.Model):
  id = db.Column(db.Integer, primary_key=True)
  name = db.Column(db.String(200), unique=True)
  brand_name = db.Column(db.String(200))
  regular_price_value = db.Column(db.Float)
  offer_price_value = db.Column(db.Integer)
  currency = db.Column(db.String(200))
  classification_l1 = db.Column(db.String(200))
  classification_l2 = db.Column(db.String(200))
  classification_l3 = db.Column(db.String(200))
  classification_l4 = db.Column(db.String(200))
  image_url = db.Column(db.String(200))

  def __init__(self, name, brand_name, regular_price_value, offer_price_value,currency,classification_l1,classification_l2,classification_l3,classification_l4,image_url):
    self.name = name
    self.brand_name = brand_name
    self.regular_price_value = regular_price_value
    self.offer_price_value = offer_price_value
    self.currency=currency
    self.classification_l1=classification_l1
    self.classification_l2=classification_l2
    self.classification_l3=classification_l3
    self.classification_l4=classification_l4
    self.image_url=image_url

# Product Schema
class ProductSchema(ma.Schema):
  class Meta:
    fields = ('id', 'name', 'brand_name', 'regular_price_value', 'offer_price_value','currency','classification_l1','classification_l2','classification_l3','classification_l4','image_url')

# Init schema
product_schema = ProductSchema()
products_schema = ProductSchema(many=True)

# Create a Product
@app.route('/product', methods=['POST'])
def add_product():
  name = request.json['name']
  brand_name = request.json['brand_name']
  regular_price_value = request.json['regular_price_value']
  offer_price_value = request.json['offer_price_value']
  currency = request.json['currency']
  classification_l1 = request.json['classification_l1']
  classification_l2 = request.json['classification_l2']
  classification_l3 = request.json['classification_l3']
  classification_l4 = request.json['classification_l4']
  image_url=request.json['image_url']

  new_product = Product(name, brand_name, regular_price_value, offer_price_value,currency,classification_l1,classification_l2,classification_l3,classification_l4,image_url)

  db.session.add(new_product)
  db.session.commit()

  return product_schema.jsonify(new_product)

# Get All Products
@app.route('/product', methods=['GET'])
def get_products():
  all_products = Product.query.all()
  result = products_schema.dump(all_products)
  return jsonify(result)

# Get Single Products
@app.route('/product/<id>', methods=['GET'])
def get_product(id):
  product = Product.query.get(id)
  return product_schema.jsonify(product)

# Update a Product
@app.route('/product/<id>', methods=['PUT'])
def update_product(id):
  product = Product.query.get(id)

  name = request.json['name']
  brand_name = request.json['brand_name']
  regular_price_value = request.json['regular_price_value']
  offer_price_value = request.json['offer_price_value']
  currency = request.json['currency']
  classification_l1 = request.json['classification_l1']
  classification_l2 = request.json['classification_l2']
  classification_l3 = request.json['classification_l3']
  classification_l4 = request.json['classification_l4']
  image_url=request.json['image_url']

  product.name = name
  product.brand_name = brand_name
  product.regular_price_value = regular_price_value
  product.offer_price_value = offer_price_value
  product.currency = currency
  product.classification_l1 = classification_l1
  product.classification_l2 = classification_l2
  product.classification_l3 = classification_l3
  product.classification_l4 = classification_l4
  product.image_url = image_url

  db.session.commit()

  return product_schema.jsonify(product)

# Delete Product
@app.route('/product/<id>', methods=['DELETE'])
def delete_product(id):
  product = Product.query.get(id)
  db.session.delete(product)
  db.session.commit()

  return product_schema.jsonify(product)

# Run Server
if __name__ == '__main__':
  app.run(debug=False)


flags = {
    "Discord Employee": 1,
    "Discord Partner": 2,
    "HypeSquad Events": 4,
    "Bug Hunter Level 1": 8,
    "Dismissed Nitro promotion": 32,
    "HypeSquad Online House Bravery": 64,
    "HypeSquad Online House Brilliance": 128,
    "HypeSquad Online House Balance": 256,
    "Early Supporter": 512,
    "Team User": 1024,
    "System User": 4096,
    "Bug Hunter Level 2": 16384,
    "Verified Bot": 65536,
    "Early Verified Bot Developer": 131072,
    "Moderator Programs Alumni": 262144,
    "Bot has set an interactions endpoint url": 524288,
    "User is disabled for being a spammer": 1048576,
    "User is an active developer": 4194304,
    "User has a premium discriminator": 137438953472,
    "User has used the desktop client": 274877906944,
    "User has used the web client": 549755813888,
    "User has used the mobile client": 1099511627776,
    "User has a verified email": 8796093022208,
    "User is a collaborator and has staff permissions": 1125899906842624,
    "User is a restricted collaborator and has staff permissions": 2251799813685248
}

premium = ['None', 'Nitro Classic', 'Nitro', 'Nitro Basic']

def parse_flags(flag):
    userFlags = []
    for i in flags.keys():
        if flags[i] & flag == flags[i]:
            userFlags.append(i)

    return userFlags

if __name__ == '__main__':
    print(parse_flags(32))


import requests
from behave import *
from decouple import config
from hamcrest import assert_that, equal_to

def parse_string(text):
    if text == "None":
        return None
    return text

register_type(string = parse_string)

@given('I am an authenticated user')
def step_impl(context):
    context.TOKEN = config('ACCESS_TOKEN')

@when('I query the user data for {user}')
def step_impl(context, user):
    headers = {
        "Authorization": "token " + context.TOKEN
    }
    context.response = requests.get(f"https://api.github.com/users/{user}", headers=headers)

@then('the {key} is {value:string}')
def step_impl(context, key, value):
    result = context.response.json()[key]
    assert_that(value, equal_to(result))

@when('I query the repo data name {repo_name} of {user}')
def query_data(context, repo_name, user):
    headers = {
        "Authorization": "token " + context.TOKEN
    }
    context.response = requests.get(f"https://api.github.com/repos/{user}/{repo_name}", headers=headers)

@then('repo full_name is {expected}')
def check_result(context, expected):
    result = context.response.json()["full_name"]
    assert_that(result, equal_to(expected))


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# File:                Ampel-interface/ampel/cli/ArgParserBuilder.py
# License:             BSD-3-Clause
# Author:              valery brinnel <firstname.lastname@gmail.com>
# Date:                17.03.2021
# Last Modified Date:  20.08.2022
# Last Modified By:    valery brinnel <firstname.lastname@gmail.com>

from typing import Any
from ampel.cli.AmpelArgumentParser import AmpelArgumentParser

class ArgParserBuilder:
	"""
	Creates one or many instances of AmpelArgumentParser
	"""

	def __init__(self, op: None | str = None) -> None:
		"""
		"""
		self.parsers: dict[str, AmpelArgumentParser] = {}
		self._op = op

	def add_parser(self, name: str, hlp: dict[str, str]) -> AmpelArgumentParser:
		parser = AmpelArgumentParser(ampel_op=self._op)
		parser.set_help_descr(hlp)
		setattr(parser, '_sub_op', name)
		self.parsers[name] = parser
		return parser

	def add_parsers(self, names: list[str], hlp: dict[str, str]) -> list[AmpelArgumentParser]:
		return [self.add_parser(el, hlp) for el in names]

	def get(self) -> dict[str, AmpelArgumentParser]:
		""" Returns parsers created during the build procedure """
		return self.parsers

	def add_group(self, group: str, title: str, sub_ops: str, **kwargs):
		"""
		:param sub_ops: see arg(...) docstring
		"""
		for p in self.get_parsers(sub_ops):
			p.groups[group] = p.add_argument_group(group, **kwargs)
			p.groups[group].title = title

	def set_group_defaults(self, group: str, sub_ops: str, **kwargs):
		"""
		:param sub_ops: see arg(...) docstring
		"""
		for p in self.get_parsers(sub_ops):
			p.groups[group].set_defaults(**kwargs)

	def description(self, descr: None | str | list[str], sub_ops: str) -> None:
		"""
		Calls method 'add_description' (see AmpelArgumentParser docstring) for the selected parser(s).
		:param sub_ops: see arg(...) docstring
		"""

		for p in self.get_parsers(sub_ops):
			p.add_description(descr)

	def opt(self, opt_name: str, sub_ops: str = 'all', **kwargs):
		return self.arg(opt_name, 'optional', sub_ops, **kwargs)

	def req(self, opt_name: str, sub_ops: str = 'all', **kwargs):
		return self.arg(opt_name, 'required', sub_ops, **kwargs)

	def arg(self, opt_name: str, group: str, sub_ops: str = 'all', **kwargs):
		"""
		:param name: option name
		:param group: group name. Multiple sub-parsers can be targeted using '|'.
		If no is specified, option will be added to all existing subparsers.
		Ex: arg('to-json', 'show|export|tail')
		"""
		for p in self.get_parsers(sub_ops):
			p.arg(opt_name, group, **kwargs)

	def xargs(self, group: str, sub_ops: str, xargs: list[dict[str, Any]]) -> None:
		"""
		Calls method 'x_args' (see AmpelArgumentParser docstring) for the selected parser(s).
		:param sub_ops: see arg(...) docstring
		"""
		for p in self.get_parsers(sub_ops):
			p.xargs(group, *xargs)

	def get_parsers(self, sub_ops: str = 'all') -> list[AmpelArgumentParser]:
		"""
		:param sub_ops: string containing one or more parser names.
		Multiple parsers can be retrieved using the separating character "|".
		"""

		if "|" in sub_ops:
			pp = sub_ops.split("|")
			for el in pp:
				if el not in self.parsers:
					raise ValueError(f"Unknown parser: '{el}', please create it using add_parser")

			ret1: list[AmpelArgumentParser] = [
				v for k, v in self.parsers.items()
				if k in pp
			]

		elif sub_ops == "all":
			ret1 = list(self.parsers.values())

		else:
			if sub_ops not in self.parsers:
				raise ValueError(f"Unknown parser: '{sub_ops}', please create it using add_parser")
			ret1 = [self.parsers[sub_ops]]

		return ret1

	def logic_args(self,
		base_name: str,
		descr: str,
		group: str,
		sub_ops: str = 'all',
		metavar: str = "#",
		required: bool = False,
		pos: None | int = None,
		ref: None | str = None,
		excl: bool = False,
		json: bool = True, **kwargs
	) -> None:
		"""
		Calls method 'create_logic_args' (see AmpelArgumentParser docstring) for the selected parser(s).
		:param sub_ops: see arg() docstring
		"""
		for p in self.get_parsers(sub_ops):
			p.logic_args(base_name, group, descr, metavar, required, pos, ref, excl, json)

	def logic_args_opt(self,
		base_name: str, descr: str, sub_ops: str = 'all', metavar: str = "#", required: bool = False,
		pos: None | int = None, ref: None | str = None, excl: bool = False, json: bool = True, **kwargs
	) -> None:
		self.logic_args(
			base_name, descr, "optional", sub_ops, metavar, required,
			pos, ref, excl, json, **kwargs
		)

	def logic_args_req(self,
		base_name: str, descr: str, sub_ops: str = 'all', metavar: str = "#", required: bool = False,
		pos: None | int = None, ref: None | str = None, excl: bool = False, json: bool = True, **kwargs
	) -> None:
		self.logic_args(
			base_name, descr, "required", sub_ops, metavar, required,
			pos, ref, excl, json, **kwargs
		)

	def note(self,
		note: str,
		sub_ops: str = 'all',
		pos: None | int = None,
		ref: None | str = None
	) -> None:
		"""
		Calls method 'note' (see AmpelArgumentParser docstring) for the selected parser(s).
		:param parsers: see _get_parsers() docstring
		"""
		for p in self.get_parsers(sub_ops):
			p.note(note, pos, ref)

	def example(self,
		sub_ops: str,
		ex: str,
		prepend = None,
		append="",
		auto_strip: bool = True, ref: None | str = None
	) -> None:
		"""
		Calls method 'example' (see AmpelArgumentParser docstring) for the selected parser(s).
		:param parsers: see _get_parsers() docstring
		"""
		for p in self.get_parsers(sub_ops):
			p.example(
				ex,
				prepend or f"ampel {self._op or ''} {getattr(p, '_sub_op', '')} ",
				append, auto_strip, ref
			)

	def hint_query_logic(self, sub_op: str, pos: None | int = None, ref: None | str = None):
		for p in self.get_parsers(sub_op):
			p.hint_query_logic(pos, ref)

	def hint_all_query_logic(self, pos: None | int = None, ref: None | str = None):
		for p in self.parsers.values():
			p.hint_query_logic(pos, ref)

	def hint_time_format(self, sub_ops: str, pos: None | int = None, ref: None | str = None):
		for p in self.get_parsers(sub_ops):
			p.hint_time_format(pos, ref)

	def hint_all_time_format(self, pos: None | int = None, ref: None | str = None):
		for p in self.parsers.values():
			p.hint_time_format(pos, ref)

	def hint_all_config_override(self, pos: None | int = None, ref: None | str = None):
		for p in self.parsers.values():
			p.hint_config_override(pos, ref)

	def notation_add_note_references(self):
		for p in self.parsers.values():
			p.notation_add_note_references()

	def notation_add_example_references(self):
		for p in self.parsers.values():
			p.notation_add_example_references()


"""
reduceByKey算子：针对KV型RDD，自动按照key分组，然后根据你提供的聚合逻辑，完成组内数据（value）的聚合操作
KV型RDD：其实就是二元元组(('a', 1), ('b', 2))
key分组：把二元中的第一个作为key，如a, b
用法：
    rdd.reduceByKey(func)
    # func: (v, v) -> v
    # 接受2个传入参数（类型要一致），返回一个返回值，类型和传入要求一致
"""
from pyspark import SparkConf, SparkContext
import os
os.environ['JAVA_HOME'] = "C:\Program Files\Java\jdk-19"  # 告诉Pycharm哪里找到java环境变量
os.environ['PYSPARK_PYTHON'] = "D:\Python3.92\python.exe"  # 告诉PySpark哪里能找到Python解释器
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)
# 准备一个RDD
rdd = sc.parallelize([('男', 99), ('男', 88), ('女', 99), ('女', 66)])
# 求男生和女生两个组的成绩之和
rdd2 = rdd.reduceByKey(lambda a, b: a + b)  # 接收一个处理函数，对数据进行两两计算
print(rdd2.collect())


import json

from flask import Flask, jsonify, request
from flask_cors import CORS
from flask_restful import Api, Resource, reqparse
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import ForeignKey, Integer, Column
from sqlalchemy.orm import relationship

db = SQLAlchemy()

app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///analysis.db"

db.init_app(app)

cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'

api = Api(app)

parser = reqparse.RequestParser()

class User(db.Model):
    __tablename__ = "user"

    id = Column(db.Integer, primary_key=True)
    name = Column(db.String(128), nullable=False)
    phone = Column(db.String(11), unique=True, nullable=False)
    uid = Column(db.String(10), unique=True, nullable=False)

    usersForTransfers = relationship("UsersForTransfers", backref='user')

    # usersForTransfersId = Column(Integer, ForeignKey('UsersForTransfers.id'))
    # usersForTransfers = relationship("UsersForTransfers")

    def __repr__(self):
        return f"<phone {self.phone}>"

    def __init__(self, phone, name, uid):
        self.phone = phone
        self.name = name
        self.uid = uid

class UsersForTransfers(db.Model):
    __tablename__ = "UsersForTransfers"

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), nullable=False)
    phone = db.Column(db.String(11), unique=True, nullable=False)
    uid = db.Column(db.String(10), unique=True, nullable=False)

    user_id = db.Column(Integer, ForeignKey('user.id'))

    def __repr__(self):
        return f"<phone {self.phone}>"

    def __init__(self, phone, name, uid, user_id):
        self.phone = phone
        self.name = name
        self.uid = uid
        self.user_id = user_id

with app.app_context():
    db.create_all()

class ListUsers(Resource):

    def get(self):

        users = User.query.all()

        listUsers = []

        for i in users:
            listUsers.append({
                'name': i.name,
                'phone': i.phone,
                'uid': i.uid,
                'users_for_transfers': []
            })
            for k in i.usersForTransfers:
                listUsers[len(listUsers)-1]['users_for_transfers'].append({
                    'name': k.name,
                    'phone': k.phone,
                    'uid': k.uid,
                    'user_id': k.user_id
                })

        return {
            "users": listUsers
        }

api.add_resource(ListUsers, '/list-users')

class AddUser(Resource):

    def post(self):
        parser.add_argument('name', type=str)
        parser.add_argument('phone', type=str)
        parser.add_argument('uid', type=str)

        name = parser.parse_args()['name']
        phone = parser.parse_args()['phone']
        uid = parser.parse_args()['uid']

        addUser = User(phone=phone, name=name, uid=uid)
        db.session.add(addUser)

        try:
            db.session.commit()
            return {
                "status": 1,
            }
        except:
            return {
                "status": 0
            }

api.add_resource(AddUser, '/add-user')

class AddUsersForTransfers(Resource):

    def post(self):
        parser.add_argument('name', type=str)
        parser.add_argument('phone', type=str)
        parser.add_argument('uid', type=str)
        parser.add_argument('users', type=str)

        name = parser.parse_args()['name']
        phone = parser.parse_args()['phone']
        uid = parser.parse_args()['uid']
        user = parser.parse_args()['users']

        users = []

        for i in user:
            usersForTransfer = User.query.get(i)
            users.append(usersForTransfer)

        addUsersForTransfer = UsersForTransfers(phone=phone, name=name, uid=uid, user_id=user)
        db.session.add(addUsersForTransfer)

        try:
            db.session.commit()
            return {
                "status": 1,
            }
        except:
            return {
                "status": 0
            }

api.add_resource(AddUsersForTransfers, '/add-users-for-transfers')


for _ in range(int(input())):
    s=input().split()
    r=0
    for i in s:
        if i=='u':
            r+=1
        if i=='ur':
            r+=1
    for i in range(len(s)-1):
        if (s[i]=="should" or s[i]=="would")and(s[i+1]=="of"):
            r+=1
    for i in s:
        if "lol" in i:
            r+=1
    print(r*10)


from django.urls import path
from . import views
from django.contrib.auth import views as auth_view

urlpatterns = [
    path('',views.index,name='index'),
    path('edit/<int:id>/',views.edit,name='edit'),
    path('delete/<int:id>/',views.delete,name='delete'),
    path('login/',views.user_login,name='login'),
    path('register/',views.register,name='register'),
    path('logout/',auth_view.LogoutView.as_view(template_name='myapp/logout.html'),name='logout')
]


from mcm.tcg import *
import numpy as np
from matplotlib import pyplot as plt
from pathlib import Path
from tcg_slb.base import *
from tcg_slb.phasediagram.scipy import ScipyPDReactiveODE
from multiprocessing import Pool
import multiprocessing as mp
from scipy.interpolate import griddata
import from_perplex as pp

SMALL_SIZE = 9
MEDIUM_SIZE = 11
BIGGER_SIZE = 13

plt.rc('font', size=SMALL_SIZE)          # controls default text sizes
plt.rc('axes', titlesize=SMALL_SIZE, titleweight="medium")     # fontsize of the axes title
plt.rc('axes', labelsize=SMALL_SIZE)    # fontsize of the x and y labels
plt.rc('xtick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('legend', fontsize=SMALL_SIZE)    # legend fontsize
plt.rc('figure', titlesize=MEDIUM_SIZE)  # fontsize of the figure title
#plt.rc('axes', titley=1.0)    # y is in axes-relative coordinates.
#plt.rc('axes', titlepad=-16)  # pad is in points...

### ======================= INPUTS ============================
reference = "parallel_pd"
composition = "hacker_2015_md_xenolith"
rxn_name = "eclogitization_agu17_stx21_rx"

# number of nodes in each dimension (T,P) = (x,y)
nP = 80
nT = 80

# end time of reactions
# override with -e arg
end_t = 1

# limit the maximum number of steps taken by the solver
# defaults to infinity, which can exhaust memory if solver doesn't converge
# a default of 4e3 seems to work well
max_steps = 4e3

# regularization parameter for compositions
# sets the minimum value for Cik
eps = 1.e-5 # default, 1.e-2

# TODO: these numbers seem to work very well with eps = 1e-5??
rtol = 1.e-5 # relative tolerance, default 1e-5
atol = 1.e-9 # absolute tolerance, default 1e-9

# Damkhoeler number - override with -d arg
Da = 1e5

Pmin, Pmax = [0.5, 2.5] # Gpa
Tmin, Tmax = [300+273.15, 1300+273.15] # K

# override with -n arg
num_processes = mp.cpu_count()-1

# Plotting options
phasetol = 1.e-5 # phases less than this cutoff don't plot, default 1.e-2
density_levels = np.arange(2600, 3820, 20)/1000.
density_ticks = np.asarray([2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8])

T_ticks = np.arange(Tmin-273.15, Tmax-273.15+200, 200)
T_tick_labels = [""] + ["{:d}".format(int(T)) for T in T_ticks[1:-1]] + [""]
T_limits = [Tmin-273.15, Tmax-273.15]

P_ticks = np.arange(Pmin, Pmax+0.5, 0.5)

highlight_densities = np.asarray([3.33] )# /10
highlight_diffs= np.asarray([0.] )

density_cmap = plt.get_cmap("Spectral_r")
diff_cmap = plt.get_cmap("bwr_r")
stime_cmap = plt.get_cmap("bwr")
stime_cmap.set_bad(color='black') # make NaNs show up as black
variance_cmap = plt.get_cmap("Blues_r")
contour_kwargs = {
    "colors": "#333333",
    "linewidths": 1,
    "linestyles": "solid",
    "linewidths": 1,
    "alpha": 0.6
}
contour_highlight_kwargs = {
    "alpha":0.6,
    "colors":"black",
    "linewidths":1,
}
imshow_kwargs = {
    "extent": (Tmin-273.15,Tmax-273.15,Pmin,Pmax),
    "origin":"lower",
    "aspect":"auto",
}

# This custom formatter removes trailing zeros, e.g. "1.0" becomes "1", and
# then adds a percent sign.
def diff_fmt(x):
    s = f"{x:.1f}"
    if s.endswith("0"):
        s = f"{x:.0f}"
    return rf"{s}"

def rel_err_fmt(x):
    s = f"{x:.1f}"
    return rf"{s}"

fig_filetypes = ["png", "pdf"]

# ===================================================

# ============= Parse arguments for CLI =============

if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("-c", "--composition")
    parser.add_argument("-e", "--end_t")
    parser.add_argument("-r", "--rxn_name")
    parser.add_argument("-n", "--num_processes")
    parser.add_argument("-d", "--damk")
    args = parser.parse_args()

    if args.composition is not None:
        print("Using composition {}".format(args.composition))
        composition = args.composition
    if args.end_t is not None:
        print("Using end time {}".format(args.end_t))
        end_t = float(args.end_t)
    if args.rxn_name is not None:
        print("Using reaction {}".format(args.rxn_name))
        rxn_name = args.rxn_name
    if args.num_processes is not None:
        num_processes = int(args.num_processes)
    if args.damk is not None:
        Da = float(args.damk)

#====================================================

# get reaction object
rxn = get_reaction(rxn_name)

mi0, Xik0, phii0, Cik0 = pp.get_point_composition(rxn, composition)

Cik0 = x2c(rxn, Xik0) if Cik0 is None else Cik0
mi0 = phi2m(rxn, phii0, Cik0, eps) if mi0 is None else mi0

T_range = np.linspace(Tmin, Tmax, nT)
P_range = np.linspace(Pmin, Pmax, nP)
P_g, T_g  = np.meshgrid(P_range, T_range, indexing="ij")

rho_g = np.zeros(P_g.shape)
stime_g = np.zeros(P_g.shape)
variance_g = np.zeros(P_g.shape)
phases_g = [["" for j in range(nT)] for i in range(nP)]

# function to run in parallel
# solves an ODE for each point in the grid given i, j indices
def task(args):
    i, j = args
    P = P_range[i]
    T = T_range[j]

    ode = ScipyPDReactiveODE(rxn)

    ode.solve(T,GPa2Bar(P),mi0,Cik0,end_t,Da=Da,eps=eps,rtol=rtol,atol=atol,method="BDF_mcm",max_steps=max_steps)
    odephasenames, phaseabbrev = ode.final_phases(phasetol)
    phases = "+".join(phaseabbrev) if ode.sol.status == 0 else ""
    rho = ode.final_rho() if ode.sol.status == 0 else np.nan
    stime = ode.stime
    variance = odephasenames.size
    return rho/10., phases, stime, variance, i, j

# Solve individual points in parallel
with Pool(num_processes, maxtasksperchild=12) as pool:
    arglist = [[i,j] for i,P in enumerate(P_range) for j,T in enumerate(T_range)]
    sols = pool.map(task, arglist)

# Collect individual points back into grids
for rho, phases, stime, variance, i , j in sols:
    rho_g[i][j] = rho
    phases_g[i][j] = phases
    stime_g[i][j] = stime
    variance_g[i][j] = variance

# Find nans in density (solution timed out)
x,y = np.indices(rho_g.shape)
rhonan = np.isnan(rho_g)

# For points that timed out, give them a solution time of NaN
stime_g[rhonan] = np.nan

# Interpolate NaNs in density
rho_g[rhonan] = griddata((x[~rhonan], y[~rhonan]),rho_g[~rhonan],(x[rhonan], y[rhonan]))

# Generate unique phase assemblage indices
uniquestrs = sorted(list(set([phstr for phstrl in phases_g for phstr in phstrl if phstr != ""])))
def index(ls,v):
    try:
        i = ls.index(v)
    except ValueError:
        i = -1
    return i
phaseis_g = np.asarray([[index(uniquestrs,phstr) for phstr in phasestrr]  for phasestrr in phases_g])

# Get pyrolite density grid
interp = pp.get_rho_interpolator("xu_2008_pyrolite", "1000kg/m3")
rho_pyrolite_g = interp((T_g, P_g))

# Create folders if needed
outputPath = Path("figs",reference,composition,rxn_name)
outputPath.mkdir(parents=True, exist_ok=True)

def save_current_fig_as(name):
    _name = name[1:] if name[0]=="." else name
    for ext in fig_filetypes:
        _ext = ext[1:] if ext[0]=="." else ext
        plt.savefig(Path(outputPath,"{}.{}".format(_name, _ext)))

def plot_phase_labels(ax):
    fxgrid = T_g.flatten()-273.15
    fygrid = P_g.flatten()
    fphaseis = phaseis_g.flatten()

    for i,ph in enumerate(uniquestrs):
        if i in fphaseis:
            indices = fphaseis==i
            ax.text(np.mean(fxgrid[indices]), np.mean(fygrid[indices]),ph,fontsize=12,ha='center',va='center',weight="bold")

# Plot density

fig = plt.figure(figsize=(12,14))
axi = fig.add_subplot(1,1,1)

s = axi.contourf(T_g-273.15,P_g,rho_g,levels=density_levels,alpha=0.75,cmap=density_cmap)
axi.contour(T_g-273.15,P_g,rho_g,levels=density_levels,alpha=1,cmap=density_cmap)
axi.contour(T_g-273.15,P_g,rho_g,levels=highlight_densities,alpha=1,colors="black")
plt.xlim(T_limits)
plt.ylim([Pmin,Pmax])
plt.colorbar(mappable=s, location="left", label="density (10$^3$ kg/m$^3$)")
plt.gca().set_title(composition_to_label(composition))
save_current_fig_as("density")

# Plot phases

fig = plt.figure(figsize=(12,14))
axi = fig.add_subplot(1,1,1)
scs = []
for i,ph in enumerate(uniquestrs):
    scs.append(axi.scatter(T_g[phaseis_g==i]-273.15,P_g[phaseis_g==i],alpha=0.35,label=ph,s=50))
fig.legend(handles=scs,loc="center left")
plot_phase_labels(axi)
plt.xlabel("Temperature (°C)", labelpad=2)
plt.ylabel("Pressure (GPa)")
plt.xlim(T_limits)
plt.xticks(T_ticks)
plt.gca().set_xticklabels(T_tick_labels)
plt.ylim([Pmin,Pmax])
plt.gca().set_title(composition_to_label(composition))
save_current_fig_as("phases")

# Plot variance

fig = plt.figure(figsize=(12,14))
axi = fig.add_subplot(1,1,1)
max_variance = np.nanmax(variance_g)
min_variance = np.nanmin(variance_g)
#s = axi.scatter(T_g-273.15,P_g,c=variance_g,s=50,cmap=variance_cmap,alpha=0.5,vmin=min_variance-1,vmax=max_variance+1)
s=axi.imshow(variance_g,cmap=variance_cmap, vmin=min_variance-1, vmax=max_variance+1,**imshow_kwargs)
plot_phase_labels(axi)
plt.xlabel("Temperature (°C)", labelpad=2)
plt.ylabel("Pressure (GPa)")
plt.xlim(T_limits)
plt.xticks(T_ticks)
plt.gca().set_xticklabels(T_tick_labels)
plt.ylim([Pmin,Pmax])
plt.gca().set_title(composition_to_label(composition))
save_current_fig_as("phase-variance")

# Plot solution time

fig = plt.figure(figsize=(12,14))
axi = fig.add_subplot(1,1,1)
s = plt.imshow(stime_g, cmap=stime_cmap,**imshow_kwargs)
#s = plt.scatter(T_g-273.15,P_g,c=stime_g,s=100,alpha=0.75,cmap=stime_cmap)#,norm=mpl.colors.LogNorm(),)
fig.colorbar(s,location="left",ax=axi, label="sol time (s)")
plt.xlabel("Temperature (°C)", labelpad=2)
plt.ylabel("Pressure (GPa)")
plt.xlim(T_limits)
plt.xticks(T_ticks)
plt.gca().set_xticklabels(T_tick_labels)
plt.ylim([Pmin,Pmax])
plt.gca().set_title(composition_to_label(composition))
save_current_fig_as("stime")

# Plot comparison with Perple_X density
interp = pp.get_rho_interpolator(composition,"1000kg/m3")
if (interp is not None):
    rho_eq_g = interp((T_g, P_g))

    fig = plt.figure(figsize=(10,5))

    axi = fig.add_subplot(1,3,1)
    s = axi.contourf(T_g-273.15, P_g, rho_g, levels=density_levels, alpha=0.75, cmap=density_cmap)
    axi.contour(T_g-273.15, P_g, rho_g, levels=density_levels, alpha=1, cmap=density_cmap)
    plt.xlim(T_limits)
    plt.xticks(T_ticks)
    plt.ylabel("Pressure (GPa)")
    plt.gca().set_xticklabels(T_tick_labels)
    plt.colorbar(mappable=s, location="bottom", ticks=density_ticks, label="Density (10$^3$ kg/m$^3$)")
    plt.gca().set_title(composition_to_label(composition))

    axi = fig.add_subplot(1,3,2)
    s = axi.contourf(T_g-273.15, P_g, rho_eq_g, levels=density_levels, alpha=0.75, cmap=density_cmap)
    axi.contour(T_g-273.15, P_g, rho_eq_g, levels=density_levels, alpha=1, cmap=density_cmap)
    plt.xlim(T_limits)
    plt.xticks(T_ticks)
    plt.xlabel("Temperature (°C)", labelpad=2)
    plt.gca().set_xticklabels(T_tick_labels)
    plt.ylim([Pmin,Pmax])
    plt.yticks([])
    plt.colorbar(mappable=s, location="bottom",ticks=density_ticks, label="Density (10$^3$ kg/m$^3$)")
    plt.gca().set_title("Equilibrium system")

    axi = fig.add_subplot(1,3,3)
    diff = (rho_g-rho_eq_g)/rho_eq_g*100
    absmax = np.ceil(np.nanmax(np.absolute(diff)))
    levels = np.arange(-absmax, absmax+1, 1)
    s=axi.imshow(diff,cmap=diff_cmap,vmin=-absmax,vmax=absmax, **imshow_kwargs)
    axi.contour(T_g-273.15 ,P_g, diff, levels=levels,**contour_kwargs)
    plt.yticks([])
    plt.colorbar(mappable=s, location="bottom", label="Relative error (%)")
    plt.xticks(T_ticks)
    plt.gca().set_xticklabels(T_tick_labels)
    plt.gca().set_title("Error")

    plt.tight_layout()
    save_current_fig_as("density_comparison")

# Plot comparison with pyrolite

fig = plt.figure(figsize=(10,5))

axi = fig.add_subplot(1,3,1)
s = axi.contourf(T_g-273.15, P_g, rho_g, levels=density_levels, alpha=0.75, cmap=density_cmap)
axi.contour(T_g-273.15, P_g, rho_g, levels=density_levels, alpha=1, cmap=density_cmap)
plt.xlim(T_limits)
plt.xticks(T_ticks)
plt.ylabel("Pressure (GPa)")
plt.gca().set_xticklabels(T_tick_labels)
plt.ylim([Pmin,Pmax])
plt.colorbar(mappable=s, location="bottom", ticks=density_ticks, label="Density (10$^3$ kg/m$^3$)")
plt.gca().set_title(composition_to_label(composition))

axi = fig.add_subplot(1,3,2)
s = axi.contourf(T_g-273.15, P_g, rho_pyrolite_g, levels=density_levels, alpha=0.75, cmap=density_cmap)
axi.contour(T_g-273.15, P_g, rho_pyrolite_g, levels=density_levels, alpha=1, cmap=density_cmap)
plt.xlim(T_limits)
plt.xticks(T_ticks)
plt.xlabel("Temperature (°C)", labelpad=2)
plt.gca().set_xticklabels(T_tick_labels)
plt.ylim([Pmin,Pmax])
plt.yticks([])
plt.colorbar(mappable=s, location="bottom", ticks=density_ticks, label="Density (10$^2$ kg/m$^3$)")
plt.gca().set_title("Pyrolite (Xu et al. 2008)")

axi = fig.add_subplot(1,3,3)
diff = (rho_g-rho_pyrolite_g)*1000 # kg/m3
maxval = np.ceil(np.nanmax(np.absolute(diff))/100)*100+50
levels = np.arange(-maxval,maxval+50,50)
s=axi.imshow(diff,cmap=diff_cmap,vmin=-maxval,vmax=maxval, **imshow_kwargs)
axi.contour(T_g-273.15, P_g, diff, levels=levels,**contour_kwargs)
plt.colorbar(mappable=s, location="bottom", label="kg/m$^3$")
plt.gca().set_title("Difference")
plt.xticks(T_ticks)
plt.gca().set_xticklabels(T_tick_labels)
plt.yticks([])

plt.tight_layout()
save_current_fig_as("density_contrast")

# Plot combined figure

fig = plt.figure(figsize=(10,5))

axi = fig.add_subplot(1,3,1)
s = axi.contourf(T_g-273.15, P_g, rho_g, levels=density_levels, alpha=0.75, cmap=density_cmap)
axi.contour(T_g-273.15, P_g, rho_g, levels=density_levels, alpha=1, cmap=density_cmap)
plt.xlim(T_limits)
plt.xticks(T_ticks)
plt.gca().set_xticklabels(T_tick_labels)
plt.ylim([Pmin,Pmax])
plt.yticks(P_ticks)
plt.colorbar(mappable=s, location="bottom", ticks=density_ticks, label="Density (10$^3$ kg/m$^3$)",pad=0.12)
plt.ylabel("Pressure (GPa)")
plt.gca().set_title("Reactive system")

axi = fig.add_subplot(1,3,2)
diff = (rho_g-rho_eq_g)/rho_eq_g*100
absmax = np.ceil(np.nanmax(np.absolute(diff))) # rounded to nearest digit
levels = np.arange(-absmax, absmax+0.2, 0.2)
label_levels = [l for i,l in enumerate(levels) if i%5==0]
s=axi.imshow(diff,cmap=diff_cmap,vmin=-absmax,vmax=absmax, **imshow_kwargs)
contours = axi.contour(T_g-273.15 ,P_g, diff, levels=levels,**contour_kwargs)
axi.clabel(contours, label_levels, inline=True, fmt=rel_err_fmt, fontsize=SMALL_SIZE)
plt.colorbar(mappable=s, location="bottom", label="rel. error (%)",pad=0.12)
plt.xticks(T_ticks)
plt.gca().set_xticklabels(T_tick_labels)
plt.yticks([])
plt.xlabel("Temperature (°C)", labelpad=2)
plt.gca().set_title("Error with equilibrium")

axi = fig.add_subplot(1,3,3)
diff = (rho_g-rho_pyrolite_g)*1000 # kg/m3
maxval = np.ceil(np.nanmax(np.absolute(diff))/100)*100+40
levels = np.arange(-maxval,maxval+20,20)
s=axi.imshow(diff,cmap=diff_cmap,vmin=-maxval,vmax=maxval, **imshow_kwargs)
contours = axi.contour(T_g-273.15, P_g, diff, levels=levels,**contour_kwargs)
contour0 = axi.contour(T_g-273.15, P_g, diff, levels=highlight_diffs,**contour_highlight_kwargs)
axi.clabel(contours, contours.levels, inline=True, fmt=diff_fmt, fontsize=SMALL_SIZE)
axi.clabel(contour0, contour0.levels, inline=True, fmt=diff_fmt, fontsize=SMALL_SIZE)
plt.colorbar(mappable=s, location="bottom", label="Difference (kg/m$^3$)", pad=0.12)
plt.gca().set_title("Density above pyrolite")
plt.xticks(T_ticks)
plt.gca().set_xticklabels(T_tick_labels)
plt.yticks([])

plt.tight_layout()

save_current_fig_as("density_summary")


"""
시작에 앞서

나는 아직 학원에서 이제 프로그래밍 언어를 어떤식으로 쓴다 정도만 배운 이제 막 코딩을 시작한 사람이다.
그래서 코딩을 해서 프로그램을 완성형으로 만든다던지 그런거 아직 할 줄 모른다...
언젠가는 내가 짠 코드를 이용해서 프로그램으로써 활용할 수 있는 날이 오면 좋겠다.

급하게 파이썬exe파일 만들기 등을 검색해보았는데 무슨 말인지 전혀 알아먹을 수가 없었고 어떤식으로 작성,작동하는 건지 조차 감이 잡히지 않는다. 이제 시작한 참이니 당연할 수도 있겠다.

그래도 지금부터라도 이런거 하나하나 만들어가보면서 조금씩 어떤식으로 하면 완성형이 되는지 알아가 보려고 한다.

어떤 프로그램을 만들 것인가?
올해 초부터 아직까지 만남을 이어오고 있는 중학교떄 친구들과 함께 계를 시작했다.
계자체가 아에 처음이라 어떤식으로 진행이 되고 돈을 걷고, 사용하고.. 전혀 알지 못하는 상태였다.
그러나 이미 한두번 계에 참가한 적이 있는 친구들의 조언(?)과 여기저기 알아본 결과를 토대로 나름의 계칙을 정하기로 하였다.

1. 회장은 1년에 한번씩 돌아가면서 한다.(생일순)

2. 계모임은 1년에 2번
    여름 여행(계곡 or 풀빌라 등) 겨울 송년회
    (회장 주도 및 계원 합의하에 변동가능)

3. 모임비는 5명이상(2/3이상)참석일때 사용
    (단, 모임은 최소 한달전에 날짜를 정해야한다. 계모임(여름, 겨울)에 한해
    해당되며 그 외에 5명이상이 모이게 될 경우 미리 공지하였고 불참자들이 동의하면 계비 사용 가능)

4. 계칙을 바꿀땐 찬반투표를 해서 5명이상(2/3이상)이 참가하고 과반의 투표를 따른다.

5. 경조사(생일,결혼식 등), 장례식등 개인부조는 각자하되
계비에서 5만원 이하의 화환(결혼, 장례식)을 그 당시의 회장이 정한다.

처음에 이런 계칙을 세운 이후에도 여러가지 얘기가 나와서 추가된 것들이 있지만 하나하나 기록해놓지 않아서 있는 것만 기록해두었다.
나중에, 추가된 계칙등을 정리한 것도 새롭게 업데이트하여 공지해두는 것이 좋을 것 같다.

다같이 모임비로써 사용함에 있어서는 불참자가 있더라도 동의를 받고 사용은 하되 총 계참가 인원에 비례하여 참가인원분만큼만 사용하도록 정했다. 예) 6명중 5명이 참가했다면 총 계비의 5/6만 사용하기로 함

이 점을 생각하여 총 사용된 여행비와 남아있는 계비등을 계산하여 이번여행에 참가한 인원이 각자 얼마를 부담하면 되는지 각자 사용한 금액만 입력하면 바로 계산해주는 프로그램을 짜보기로 했다.

코드를 직접 짜보자!
"""

a = int(input("계에 참가하고 있는 총 인원 수>>"))
b = int(input("이번 여행에 참가한 총 인원 수>>"))
c = int(input("현재 남은 총 계비는>>"))
x = (c*b)//a
print("현재 사용할 수 있는 계비는",x,"원 입니다.")

m1 = 1 #친구1
m2 = 1 #친구2
m3 = 1 #친구3
m4 = 1 #친구4
m5 = 1 #친구5

result1 = 0 #친구1의 사용금액
result2 = 0 #친구2의 사용금액
#돈을 낸사람의 수에 따라 유동적으로 추가 및 제거가능

while m1 != 0 :
    m1 = int(input("친구1이 사용한 금액은 >>"))
    result1 += m1
    print("친구1이 총 사용한 금액은",result1,"원 입니다.")
while m2 != 0 :
    m2 = int(input("친구2가 사용한 금액은 >>"))
    result2 += m2
    print("친구2가 총 사용한 금액은",result2,"원 입니다.")
#마찬가지로 돈을 쓴 사람에 따라 반복문 개수 따로 설정
#이것 또한 돈을 낸사람이 몇명인지 숫자를 입력받게 하여 따로 반복문을 돌릴 수 있을 것 같지만 당장에 그런 코드가 떠오르지 않아 현재 내 머리로 가능한 수준으로만 만들었다.

result = result1 + result2 #총 사용금액
print("총 사용금액은",result,"원 입니다.")
y = 0 #추가로 내야할 돈
z = 0 #추가비용 인원 수대로 나눈 금액

if result > x :
    y = result - x
    z = y // b
    m1 = z - result1
    m2 = z - result2
    m3 = z
    m4 = z
    m5 = z
    print("친구1이 내야할 금액은",m1,"원 입니다.")
    print("친구2가 내야할 금액은",m2,"원 입니다.")
    print("친구3이 내야할 금액은",m3,"원 입니다.")
    print("친구4가 내야할 금액은",m4,"원 입니다.")
    print("친구5가 내야할 금액은",m5,"원 입니다.")
else: print("계비만으로 충당가능한 금액이기에 추가지불할 필요가 없습니다.")

"""
느낀점
실제로 이 코드를 이용하여 쉽게 정산을 완료했다.
물론 이 코드를 짤 시간에 그냥 계산기 두드리면서 계산했으면 더 빨리 계산 가능했을지도 모르겠다.

그래도 이런 시도하나하나 해보는 것이 내 코딩인생에 어떤식으로든 도움이 될거라 믿어
의심치않고, 이런 프로그램들을 짜보면서 당연히 언젠간 막히는 날도 있을 것이다. 그럴 때, 어떤 방법을 사용하면 되는가 구글링을 해보며 새로 배우는 것도 많을 것이고,
나아가 exe파일등을 만들어 다른사람들도 무언가 필요에 의해 내가 짠 코드를 이용해 쉽게 계산하고 일 처리가 가능하게 되었으면 좋겠다고 생각한다.
"""


import os
from celery import Celery
from celery.schedules import crontab

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'NewsPortal_HW.settings')

app = Celery('NewsPortal_HW')
app.config_from_object('django.conf:settings', namespace='CELERY')

app.autodiscover_tasks()

app.conf.beat_schedule = {
    'weekly_notification_to_subscribers': {
        'task': 'portal_app.tasks.weekly_subscribers_notification',
        'schedule': crontab(hour=8, minute=0, day_of_week='monday'),
        'args': (),
    },
}


"""
Date: 2023.08.25
Author: Lv
This code is for getting the building pixels of which the value represent the change statu.
This code is to provide the data needed in GetChangedRate
"""
import os
from tools import *
import tiffile as tif
import numpy as np

citynames = ['Beijing', 'Nanjing', 'Tianjin', 'Guangzhou', 'Chongqing', 'Haerbin', 'Hangzhou',
             'Kunming', 'Nanchang', 'Shanghai', 'Shenzhen', 'Wuhan', 'Xiamen', 'Xian', 'Zhengzhou',
             'Aomen', 'Baoding', 'Changchun', 'Changsha', 'Changzhou', 'Chengdu', 'Dalian', 'Dongguan',
             'Eerduosi', 'Foshan', 'Fuzhou', 'Guiyang', 'Haikou', 'Hefei', 'Huhehaote', 'Huizhou',
             'Jinan', 'Lanzhou', 'Lasa', 'Luoyang', 'Nanning', 'Ningbo', 'Quanzhou', 'Sanya', 'Shantou',
             'Shijiazhuang', 'Suzhou', 'Taiyuan', 'Taizhou', 'Tangshan', 'Wenzhou', 'Xianggang',
             'Xining', 'Yangzhou', 'Yinchuan', 'Zhongshan', 'Jiaxing', 'Jinhua', 'Nantong',
             'Qingdao', 'Shaoxing', 'Shenyang', 'Wuxi', 'Wuhu', 'Xuzhou', 'Zhuhai']

print(len(citynames))
city_filenames = []
for cityname in citynames:
    city_filename = cityname + '.tif'
    city_filenames.append(city_filename)
print(city_filenames)

root_path = r'F:\ExperimentData\Zeping5YearsBuildings\61Cities'
lab_path = r'F:\ExperimentData\Zeping5YearsBuildings\RoIs\Label_bk0'
save_path = r'F:\ExperimentData\Zeping5YearsBuildings\61Cities\allDiffs'
make_dir(save_path)
init_year = 2018
years = [2017, 2019, 2020, 2021]

for root, dirs, files in os.walk(os.path.join(root_path, str(init_year))):
    for file in files:
        if file in city_filenames:
            file_path = os.path.join(root, file)
            print('processing', file)
            city_thisyear = tif.imread(file_path.replace(file, file.split(".")[0] + '51N_clip.tif'))  # value = 255, bk = 0
            lab = tif.imread(os.path.join(r'F:\ExperimentData\Zeping5YearsBuildings\RoIs\Label_bk0', file))  # value = nos, bk = 0

            city_thisyear = np.where(lab != 0, city_thisyear / 255, 0)

            city_diff_all = np.zeros_like(city_thisyear)

            for year in years:
                file_other_path = file_path.replace('2018', str(year))
                city_otheryear = tif.imread(file_other_path.replace(file, file.split(".")[0] + '51N_clip.tif'))
                city_otheryear = np.where(lab != 0, city_otheryear / 255, 0)

                city_diff_tmp = np.where(city_thisyear!=city_otheryear, 1, 0)

                city_diff_all += city_diff_tmp  # 5 if all year has building, 0 if no year has building, 1-4 if some year has building
            tif.imsave(os.path.join(save_path, file), city_diff_all)


import time
import random

def get_divisor(n):
    '''
    Get a random divisor of n.
    :param n: The number
    :return: a divisor of n
    '''
    l = []
    for i in range(1, n + 1):
        if n % i == 0:
            l.append(i)
    return random.choice(l)

if __name__ == '__main__':
    ops = ['+', '-', '*', '/']
    start_time = time.time()
    total = 0
    correct = 0
    questions = []
    # while seconds is less than 60
    while time.time() - start_time <= 60:
        a = random.randint(1, 99)
        op = random.choice(ops)
        if op == '/':
            # if op is '/' then b is a divisor of a
            b = get_divisor(a)
        else:
            b = random.randint(1, 99)
        # Get the correct answer
        a_op_b = '{}{}{}'.format(a, op, b)
        c = int(eval(a_op_b))

        # Let user input answer
        try:
            ans = int(input('{} = '.format(a_op_b)))
        except:
            ans = ''

        # To check if correct or not
        if time.time() - start_time <= 60:
            if c == ans:
                print('Correct! Time remain {} seconds.'.format(int(60 - (time.time() - start_time))))
                correct = correct + 1
            else:
                print('Wrong answer! Time remain {} seconds.'.format(int(60 - (time.time() - start_time))))
            total = total + 1
            questions.append('{}={}'.format(a_op_b, ans))

    print('{} questions and your correct rate is {:.2f}%'.format(total, correct / total * 100))
    for q in questions:
        print(q)


# the 'name' value as called by the {% url %} template tag

from django.urls import path

from . import views

# Set application namespace
app_name = 'scheduler'
urlpatterns = [
# /scheduler/
    # Temporary index that routes '' to 'content/'
    path('', views.IndexView.as_view(), name='index'),
    # path('', views.ContentListView.as_view(), name='index'),
    path('content/', views.ContentListView.as_view(), name='content-list'),
# /scheduler/new/
    path('content/new/', views.ContentCreateView.as_view(), name='content-add'),
# /scheduler/edit/3/
    path('content/<int:pk>/edit/', views.ContentUpdateView.as_view(), name='content-update'),
# /scheduler/3/delete/
    path('content/<int:pk>/delete/', views.ContentDeleteView.as_view(), name='content-delete'),
# /scheduler/3/
    path('content/<int:pk>/', views.ContentDetailView.as_view(), name='content-detail'),
    # path('<int:content>/<int:post>/', views.PostListView.as_view(), name='post-list'),
    # I don't know why I have to reverse this, but it works.
    # Trying '<pk>/<post>/' gives me a backwards url and can't access all posts.
    # Pay attention to order in content_detail.html as well.
    path('content/<int:post>/<int:pk>/', views.PostDetailView.as_view(), name='post-detail'),
]


from bot import loaded_modules_dict
from bot import telnet_prefixes
from os import path, pardir

module_name = path.basename(path.normpath(path.join(path.abspath(__file__), pardir, pardir)))
trigger_name = path.basename(path.abspath(__file__))[:-3]

def main_function(origin_module, module, regex_result):
    next_blood_moon = regex_result.group("next_BloodMoon")
    event_data = ['update_bloodmoon_date', {
        'blood_moon_date': next_blood_moon,
    }]
    module.trigger_action_hook(origin_module, event_data=event_data)

triggers = {
    "BloodMoon SetDay": r"BloodMoon\sSetDay:\sday\s(?P<next_BloodMoon>\d+)"
}

trigger_meta = {
    "description": "reacts to updated BloodMoon date in the telnet-stream",
    "main_function": main_function,
    "triggers": [
        {
            "regex": (
                telnet_prefixes["telnet_log"]["timestamp"] +
                triggers["BloodMoon SetDay"]
            ),
            "callback": main_function
        }
    ]
}

loaded_modules_dict["module_" + module_name].register_trigger(trigger_name, trigger_meta)


""" Convert Map elite log to a pickle file with all data"""
import pickle
import numpy as np
file=open("./../logs/map_elites/set_3/map_elites_results_log.txt","r")
lines=file.readlines()
file.close()
data={}

run=0
for i in range(len(lines)):
    line=lines[i].strip()
    if "Validation" in line:
        data[run]=dict()
        ind=lines[i+2].strip()
        lis=list(lines[i+3].strip().split())
        print(run,lis[-2],lis[-3])
        # print(ind)
        data[run]['ind']=ind

        data[run]['dev']=float(lis[-3 + (run==30)])
        data[run]['makespan']=int(lis[-2 + (run==30)])

        run+=1
print(data)
file=open("./../map_elites_data_3","wb")
pickle.dump(data,file)
file.close()

file=open("./../map_elites_data_3","rb")
data_new=pickle.load(file)
print(data_new)
makespans=[]
devs=[]
for i in data_new:
    makespans.append(data[i]['makespan'])
    devs.append(data[i]['dev'])

print("All aggregates : ",makespans)
makespans=np.array(makespans)
print("Mean ",np.mean(makespans))
print("Median", np.median(makespans))
print("STD",np.std(makespans))
print("MIN",np.min(makespans))
print("MAX",np.max(makespans))

print("All aggregates : ",devs)
devs=np.array(devs)
print("Mean ",np.mean(devs))
print("Median", np.median(devs))
print("STD",np.std(devs))
print("MIN",np.min(devs))
print("MAX",np.max(devs))


import os
import pandas as pd
import system_analyses as sysev
import house_analyses as hev
import battery_analyses as bev
import EV_analyses as EVev
import market_analyses as mev
import welfare_analyses as wev
from numpy import arange

import matplotlib.pyplot as ppt
from matplotlib.dates import DayLocator, HourLocator, DateFormatter, drange

#Which run
run = 'FinalReport2'
settings_file = '/Users/admin/Documents/powernet/powernet_markets_mysql/settings_final2.csv'
df_settings = pd.read_csv(settings_file)
inds = ['0001','0025','0059']

start = pd.Timestamp(2015, 7, 16)

#Start figure
fig = ppt.figure(figsize=(9,3),dpi=150)
ppt.ioff()
ax = fig.add_subplot(111)
lns = None

ind = inds[1]
folder = '/Users/admin/Documents/powernet/powernet_markets_mysql/'+run + '_' + ind
directory = run + '_' + ind + '_vis'
df_system = pd.read_csv(directory+'/df_system.csv',index_col=[0], parse_dates=True)
C = df_settings.loc[(df_settings['run'] == run) & (df_settings['id'] == int(ind))]['line_capacity'].iloc[0]/1000
ax.plot(df_system.index,[C]*len(df_system.index),'r',linewidth=1.0,dashes=[5,5])
ax.plot(df_system.index,[0.0]*len(df_system.index),'k',linewidth=1.0)

ax2 = ax.twinx()
ax2.set_ylabel('Price [USD/MW]')
lns = ax2.plot(df_system.index,df_system['WS'],'k',label='WS price',dashes=[2.5,2.5])
lns = lns + ax2.plot(df_system.index,df_system['clearing_price'],'k',label='LEM price')

labels= ['no market/no devices','25% PV/25% Batteries, no constraint','25% PV/25% Batteries, C = '+str(C)+' MW']

i = 0
for ind in inds:
	folder = '/Users/admin/Documents/powernet/powernet_markets_mysql/'+run + '_' + ind
	directory = run + '_' + ind + '_vis'
	df_system = pd.read_csv(directory+'/df_system.csv',index_col=[0], parse_dates=True)
	flex_houses = df_settings.loc[(df_settings['run'] == run) & (df_settings['id'] == int(ind))]['flexible_houses']
	lns = lns + ax.plot(df_system.index,df_system['measured_real_power'],label=labels[i])
	i += 1

ax.set_ylabel('Measured system load [MW]')
ax.set_xlim(xmin=start, xmax=df_system.index[-1])
#ax.set_ylim(ymin=0.0, ymax=2.0)

ax.xaxis.set_major_locator(HourLocator(arange(0, 25, 3)))
ax.xaxis.set_minor_locator(HourLocator(arange(0, 25, 6)))
ax.xaxis.set_major_formatter(DateFormatter('%H:%M'))

#lns = lns + ax2.plot(df_system.index,df_system['WS'],'k',dashes=[5, 5, 5, 5],label='WS price')
ax2.xaxis.set_major_locator(HourLocator(arange(0, 25, 3)))
ax2.xaxis.set_minor_locator(HourLocator(arange(0, 25, 6)))
ax2.xaxis.set_major_formatter(DateFormatter('%H:%M'))

#Legend
labs = [l.get_label() for l in lns]
L = ax.legend(lns, labs, bbox_to_anchor=(0.5, -0.4), loc='lower center', ncol=3)
ppt.savefig(run+'/10_measuredload_Batteries.png', bbox_inches='tight')


import os
import itertools

import numpy as np

from sentence_transformers import SentenceTransformer, util
from pyserini.search.lucene import LuceneSearcher

MODEL_NAMES = {
    "mpnet": "sentence-transformers/all-mpnet-base-v2"
}

class Retriever_KG(object):
    def __init__(self, args):
        super(Retriever_KG, self).__init__()

        self.args = args

        self.model = self.get_model()

    def get_model(self):
        return SentenceTransformer(
            MODEL_NAMES[self.args.retriever_name],
            cache_folder = self.args.cache_dir
        )

    def get_triplets(self, samples, kg):
        batch_question_entities = [list(set(
            [entity['name'] for entity in sample['question_entities']]))
            for sample in samples
        ]
        batch_raw_triplets = [list(itertools.chain(*
            [kg.get_triplets(entity)['raw_triplets'] for entity in question_entities]))
            for question_entities in batch_question_entities
        ]
        batch_ver_triplets = [list(itertools.chain(*
            [kg.get_triplets(entity)['ver_triplets'] for entity in question_entities]))
            for question_entities in batch_question_entities
        ]

        assert len(samples) == \
               len(batch_question_entities) == \
               len(batch_raw_triplets) == \
               len(batch_ver_triplets)

        return batch_raw_triplets, batch_ver_triplets

    def encode(self, sentences):
        return self.model.encode(
            sentences,
            batch_size=self.args.retriever_batch_size,
            show_progress_bar=False,
        )

    def filter_triplets(self, raw_triplets, ver_triplets):
        indices = [
            index for index, triplet in enumerate(ver_triplets)
            if triplet[0] not in [None, ''] and \
               triplet[1] not in [None, ''] and \
               triplet[2] not in [None, '']
        ]
        return [raw_triplets[index] for index in indices], \
               [ver_triplets[index] for index in indices]

    def retrieve(self, samples, kg, return_ids=True, offset=0, *args, **kwargs):
        batch_raw_triplets, batch_ver_triplets = self.get_triplets(samples, kg)

        raw_results, ver_results = [], []

        for sample, raw_triplets, ver_triplets in zip(samples, batch_raw_triplets, batch_ver_triplets):
            assert len(raw_triplets) == len(ver_triplets)

            query = sample['question']
            raw_triplets, ver_triplets = self.filter_triplets(raw_triplets, ver_triplets)

            if len(ver_triplets) == 0:
                raw_results.append([])
                ver_results.append([])
                continue

            query_embedding = self.encode([query])
            triplet_embeddings = self.encode([
                f"{triplet[0]}{self.args.retriever_sep_token}{triplet[1]}{self.args.retriever_sep_token}{triplet[2]}"
                for triplet in ver_triplets
            ])
            similarities = util.dot_score(query_embedding, triplet_embeddings)[0].numpy()

            sorted_indices = np.argsort(-similarities)
            sorted_raw_triples = [raw_triplets[index] for index in sorted_indices]
            sorted_ver_triples = [ver_triplets[index] for index in sorted_indices]

            raw_results.append(sorted_raw_triples[offset*self.args.retriever_top_k:(offset+1)*self.args.retriever_top_k])
            ver_results.append(sorted_ver_triples[offset*self.args.retriever_top_k:(offset+1)*self.args.retriever_top_k])

        return ver_results if return_ids == False \
               else (ver_results, raw_results)

class Retriever_Wiki(object):
    def __init__(self, args):
        super(Retriever_Wiki, self).__init__()

        self.args = args

        self.set_cache_dir(self.args.index_dir)
        self.model = self.get_model()

    def set_cache_dir(self, dir):
        os.environ['PYSERINI_CACHE'] = dir

    def get_model(self):
        return LuceneSearcher.from_prebuilt_index('enwiki-paragraphs')

    def retrieve(self, samples, return_ids=True, offset=0, *args, **kwargs):
        results = [
            self.model.search(sample['question'])[offset:]
            for sample in samples
        ]

        raw_results = [
            [(doc.docid, doc.score) for doc in docs]
            for docs in results
        ]

        ver_results = [
            [doc.raw for doc in docs]
            for docs in results
        ]

        return ver_results if return_ids == False \
               else (ver_results, raw_results)