import os
import json
from urllib import request
import boto3
import logging
import create_message

# ロガー作成
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# DBインスタンス作成
dynamodb = boto3.resource('dynamodb')

# テーブルの定義
user_table = dynamodb.Table('intern-groupa-user')
group_table = dynamodb.Table('intern-groupa-group')

############## 以下に処理を記述 ##############

text_list = [
    "第1ステップ",
    "第2ステップ"
]

progress_list = [
    "50%",
    "100%"
]

contents_list = [
    "「＠」を入力する",
    "グループチャットに入っている人の名前の一覧が表示されるので、メンションをしたい人を選択する。",
]

def check_image(event):
    event_type = event['events'][0]['type']
    if event_type != 'message':
        # 返信内容は仮
        messages = [
            {
                "type":"flex",
                "altText": "mission message",
                "contents":create_message.create_failure_message()
            }
        ]
        return messages

    message_type = event['events'][0]['message']['type']
    if message_type == 'image':
        # 返信内容は仮
        messages = [
            {
            	"type": "flex",
            	"altText": "mission message",
            	"contents": create_message.create_congrats_message(30)
            },
            {
            	"type": "flex",
            	"altText": "mission message",
            	"contents": create_message.create_mission_message("ミッション3", 3, "https://laviespa.com/wp/wp-content/uploads/2018/03/%EF%BC%A0%E7%99%BD%E5%9C%B0%E7%B7%91%E6%96%87%E5%AD%97.png", "👉メンションをしてみよう👈")
            },
            {
                "type": "flex",
                "altText": "mission procedure",
                "contents": create_message.create_procedure_message(text_list, progress_list, contents_list)
            }
        ]
        # mission_idを更新
        group_id = event['events'][0]['source']['groupId']
        group_table.update_item(
            Key={'id': group_id},
            UpdateExpression="set mission=:m",
            ExpressionAttributeValues={
                ':m': '3'
            }
        )
        # pointを更新
        target_id = group_table.get_item(Key={'id': group_id})['Item']['target']
        point = int(user_table.get_item(Key={'id': target_id})['Item']['point'])
        user_table.update_item(
            Key={'id': target_id},
            UpdateExpression="set point=:p",
            ExpressionAttributeValues={':p': str(point + 100)}
            )
    else:
        messages = [
            {
                "type":"flex",
                "altText": "mission message",
                "contents":create_message.create_failure_message()
            }
        ]
    return messages


import re
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import selenium.common.exceptions as SeleniumEXC
from PIL import Image
import pytesseract

from conn import DatabaseConnection

class Scraper:
    def __init__(self, database_path, **kwargs):
        self.database_path = database_path
        self.driver = webdriver.Chrome('C:/Users/edu/Downloads/driver/chromedriver.exe')
        self.state = kwargs.get('state', None)
        self.city = kwargs.get('city', None)
        self.beach = kwargs.get('beach', None)

    def select_from_db(self):
        if self.beach:
            with DatabaseConnection(self.database_path) as cursor:
                select_query = "SELECT * FROM locations_2 WHERE beach=?"
                results = cursor.execute(select_query, (self.beach,))
                return results.fetchall()
        elif self.city:
            with DatabaseConnection(self.database_path) as cursor:
                select_query = "SELECT * FROM locations_2 WHERE city=?"
                results = cursor.execute(select_query, (self.city,))
                return results.fetchall()
        elif self.state:
            with DatabaseConnection(self.database_path) as cursor:
                select_query = "SELECT * FROM locations_2 WHERE state=?"
                results = cursor.execute(select_query, (self.state,))
                return results.fetchall()
        else:
            with DatabaseConnection(self.database_path) as cursor:
                select_query = "SELECT * FROM locations_2"
                results = cursor.execute(select_query)
                return results.fetchall()

    def main(self, db_rows, path_to_save_data, path_to_db):
        if db_rows:
            for idx, row in enumerate(db_rows):
                beach_name = row[2]
                city_name = row[1]
                state_name = row[0]
                wind_key = row[3]
                was_successful = self.search_coords(idx, state_name, city_name, beach_name, wind_key,
                                                    path_to_save_data, path_to_db)
                if not was_successful:
                    similar = self.similar_name(beach_name)
                    second_try = self.search_coords(idx, state_name, city_name, similar, wind_key,
                                                    path_to_save_data, path_to_db)
                    if not second_try:
                        print(f'problem with coords at {beach_name}')

    def search_coords(self, idx, state, city, beach, wind_key, path_to_save_data, path_to_db):
        bot = self.driver
        bot.get('https://www.google.com/')
        element = WebDriverWait(bot, 5).until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="tsf"]/div[2]/div[1]/div[1]/div/div[2]/input')))
        element.click()
        element.send_keys(f'{beach} {city} coordinates')
        element.send_keys(Keys.ENTER)
        try:
            WebDriverWait(bot, 1).until(
                EC.presence_of_element_located((By.XPATH, '//*[@id="Rzn5id"]/div/a[2]'))).click()
        except SeleniumEXC.TimeoutException:
            pass
        try:
            bot.find_element_by_xpath(
                '/html/body/div[6]/div[2]/div[9]/div[1]/div[2]/div/div[1]/div[2]/div/p/a[1]').click()
        except SeleniumEXC.NoSuchElementException:
            pass
        try:
            only_eng_pref = bot.find_element_by_xpath(
                '/html/body/div[6]/div[2]/div[9]/div[1]/div[2]/div/div[1]/div[2]/div/div/a[1]')
        except SeleniumEXC.NoSuchElementException:
            coords_crop = (200, 350, 900, 450)
            coords = self.save_coords(coords_crop, path_to_save_data, beach, city)
            lat, lon = self.check_coords(coords, beach)
            if lat and lon:
                self.save_to_db(state, city, beach, wind_key, lat, lon, path_to_db)
                return True
            else:
                return False
        else:
            lower_crop = (150, 400, 900, 500)
            coords = self.save_coords(lower_crop, path_to_save_data, beach, city)
            lat, lon = self.check_coords(coords, beach)
            if lat and lon:
                self.save_to_db(state, city, beach, wind_key, lat, lon, path_to_db)
                return True
            else:
                only_eng_pref.click()
                sleep(0.5)
                coords_crop = (200, 350, 900, 450)
                coords = self.save_coords(coords_crop, path_to_save_data, beach, city)
                lat, lon = self.check_coords(coords, beach)
                if lat and lon:
                    self.save_to_db(state, city, beach, wind_key, lat, lon, path_to_db)
                    return True
                else:
                    return False

    def save_coords(self, crop_coords, path_to_save_data, beach, city):
        bot = self.driver
        full_path = f'{path_to_save_data}/{city}#{beach}.png'
        bot.save_screenshot(full_path)
        coords_image = Image.open(full_path)
        cropped_coords = coords_image.crop(crop_coords)
        get_path = f'{path_to_save_data}/#{city}#{beach}.png'
        cropped_coords.save(get_path)
        return pytesseract.image_to_string(get_path)

    @staticmethod
    def check_coords(content, beach):
        expression = '(.+)(°|") (S|W), (.+)(°|") (S|W)'
        matches = re.search(expression, content)

        try:
            matches.group(0)
        except AttributeError:
            return False, False
        else:
            minus = ['W', 'S']
            lat = matches.group(1)
            signal_1 = matches.group(3)
            lon = matches.group(4)
            signal_2 = matches.group(6)
            if signal_1 in minus:
                try:
                    final_lat = float(lat) - 2 * float(lat)
                except ValueError:
                    lat_2 = lat.replace(' ', '')
                    try:
                        final_lat = float(lat_2) - 2 * float(lat_2)
                    except:
                        print(f'problem with {beach} coords')
            if signal_2 in minus:
                try:
                    final_lon = float(lon) - 2 * float(lon)
                except ValueError:
                    lon_2 = lon.replace(' ', '')
                    try:
                        final_lon = float(lon_2) - 2 * float(lon_2)
                    except:
                        print(f'problem with {beach} coords')
            try:
                return final_lat, final_lon
            except NameError:
                return None, None
            except:
                return None, None

    @staticmethod
    def save_to_db(state, city, beach, wind, lat, lon, path_to_db):
        with DatabaseConnection(path_to_db) as cursor:
            cursor.execute('INSERT INTO locations_4 VALUES (?,?,?,?,?,?)',
                           (state, city, beach, wind, lat, lon))

    @staticmethod
    def similar_name(name):
        expression = r'(Praia|Prainha|praia|prainha|Canto|canto)( Do| Da| De| Di| Du| Dos| Das| Des| Dis| Dus| | do| dos| das| da| des| de)(.+)'
        matches = re.search(expression, name)
        try:
            filtered_name = matches.group(3)
        except AttributeError:
            print(f'error with regex filtering in {name}')
        else:
            return filtered_name

scraper = Scraper('./scraper/database/brazil_1.db')
rows = scraper.select_from_db()
scraper.main(rows, './testando', './scraper/database/brazil_1.db')


import logging
import os as env_os
import dotenv
from async_main import collect_data
from aiogram import Bot, Dispatcher, executor, types
from aiogram.dispatcher.filters import Text
from aiofiles import os

dotenv.load_dotenv('.env')

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    level=logging.INFO)

logger = logging.getLogger(__name__)
# TOKEN_API_TELEBOT = env_os.environ.get('TOKEN_API_TELEBOT')
bot = Bot(token= env_os.environ.get('TOKEN_API_TELEBOT'))
dp = Dispatcher(bot)

@dp.message_handler(commands='start')
async def start(message: types.Message):
    start_buttons = ['Moscow', 'Ekaterinburg']
    keyboard = types.ReplyKeyboardMarkup(resize_keyboard=True)
    keyboard.add(*start_buttons)
    await message.answer('Please select a City', reply_markup=keyboard)

@dp.message_handler(Text(equals='Moscow'))
async def moscow_city(message: types.Message):
    await message.answer('Please waiting...')
    chat_id = message.chat.id
    await send_data(city_code='2398', chat_id=chat_id)

@dp.message_handler(Text(equals='Ekaterinburg'))
async def ekb_city(message: types.Message):
    await message.answer('Please waiting...')
    chat_id = message.chat.id
    await send_data(city_code='1869', chat_id=chat_id)

async def send_data(city_code='', chat_id=''):
    file = await collect_data(city_code=city_code)
    await bot.send_document(chat_id=chat_id, document=open(file, 'rb'))
    await os.remove(file)

if __name__ == '__main__':
    executor.start_polling(dp)


def all_thing_is_obj(object: any) -> int:
    type_names = {
        list: "List",
        tuple: "Tuple",
        set: "Set",
        dict: "Dict",
        str: "String"
    }

    name = type_names.get(type(object), "NotFound")
    if (name == "String"):
        print(f"{object} is in the kitchen : {type(object)}")
    elif (name == "NotFound"):
        print("Type not found")
    else:
        print(f"{name}: {type(object)}")
    return 42


class WeirbHrpcError(Exception):
    """Base class of WeirbHrpc Errors"""

class DependencyError(WeirbHrpcError):
    """Dependency Error"""

class ConfigError(WeirbHrpcError):
    """Config Error"""

class AppNotFound(WeirbHrpcError):
    """App Not Fount"""

class HrpcError(WeirbHrpcError):
    """Base class for HRPC Errors"""

    code = None

    def __init__(self, message=None, data=None):
        if self.code is None:
            raise RuntimeError(f'{type(self).__name__} can not instantiated')
        self.message = message or self.code
        self.data = data

    def __repr__(self):
        return f'<{type(self).__name__} {self.code}>'

class MethodNotFound(HrpcError):
    """Method not found in relevant service"""
    code = 'Hrpc.Client.MethodNotFound'

class InvalidRequest(HrpcError):
    """Request format invalid"""
    code = 'Hrpc.Client.InvalidRequest'

class InvalidParams(HrpcError):
    """Request params invalid"""
    code = 'Hrpc.Client.InvalidParams'

class InternalError(HrpcError):
    """Service internal error"""
    code = 'Hrpc.Server.InternalError'

class InvalidResult(HrpcError):
    """Service response an invalid result"""
    code = 'Hrpc.Server.InvalidResult'

BUILTIN_HRPC_ERRORS = [
    MethodNotFound,
    InvalidRequest,
    InvalidParams,
    InternalError,
    InvalidResult,
]


#!/usr/bin/python3
"""returns number of users in a subreddit"""

import requests

def number_of_subscribers(subreddit):
    """
    get number of subscribers
    if subreddit is not valid return 0

    Args::
        subreddit
    """
    reddit_url = "https://www.reddit.com/r/{}/about.json".format(subreddit)
    headers = {
            "User-Agent": "linux:0x16.api.advanced:v1.0.0 (by /u/bdov_)"
            }

    response = requests.get(reddit_url, headers=headers, allow_redirects=False)

    if response.status_code == 404:
        return 0
    results = response.json().get("data")
    return results.get("subscribers")


import sys
import os
from functools import partial

import tensorflow as tf
from matplotlib import pyplot as plt
import matplotlib as mpl
import numpy as np
import glob

from attoDNN.attodataset import AttoDataset
import attoDNN.data_generator as dg
import attoDNN.train_utils as tu
import attoDNN.preprocess as pp
import attoDNN.evaluation_utils as eu

import argparse
import pickle

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Evaluate a list of models on selected datasets.')
    parser.add_argument('datasets_list_txt', type=str, help='TXT List of datasets to evaluate on. '
                                                            'If the model was trained on specific dataset,'
                                                            'evaluation on this dataset is split into _training '
                                                            'and test (no extra suffix) parts.')
    parser.add_argument('models_path', type=str, help='*.h5 keras models.')
    parser.add_argument('output_pickle', type=str, help='Path to save pickle results of evaluation.', default='.')
    parser.add_argument('--gpu', action='store_true', help='Use GPU for predictions.')
    parser.add_argument('--batch_size', type=int, help='Batch size for predictions. Decrease if OOM errors occur.',
                        default=10)
    parser.add_argument('--save_plot', action='store_true', help='Whether to save plot with pred-true values.')
    parser.add_argument('--only_test', action='store_true', help='Predict only on the test data disregarding train data.')
    parser.add_argument('--feature', type=str, default='Up', help='Feature to predict.', choices=['Up', 'N', 'CEP'])
    parser.add_argument('--threshold', type=float, default=1e-6, help='Threshold for lowest value in preprocessing.')
    parser.add_argument('--remove_region_around_origin', action='store_true', help='Whether to remove the region (rectangle) around origin. Size can be specified by frac_x_remove, frac_y_remove.')
    parser.add_argument('--frac_x_remove', type=float, default=0.5, help='Fraction of first axis to remove. Not applied if remove_region_around_origin not specified.')
    parser.add_argument('--frac_y_remove', type=float, default=0.3, help='Fraction of second axis to remove. Not applied if remove_region_around_origin not specified.')
    parser.add_argument('--use_data_generator', action='store_true', help='Whether to use the data generator (parameters except SL hardcoded in the source) to test the model. That is, the data is augmented also during testing phase which is a non-standard practice.')
    parser.add_argument('--saturation_level_min', type=float, default=1.0, help='Minimal (worst-case) detector saturation level, in the range (-1, 1). Used only if --use_data_generator is used.'),
    parser.add_argument('--num_data_gen_realizations', type=int, default=1, help='How many independent random realizations of the data generator are used. Used only if --use_data_generator is used.'),
    parser.add_argument('--auto_saturation_level_min', action='store_true', help='Automatic minimal (worst-case) detector saturation level, in the range (-1, 1). '
                                                                                'Determined based on model filename which contains info about SL. Used only if --use_data_generator is used.'),
    args = parser.parse_args()

    with open(args.datasets_list_txt, 'r') as f:
        datasets_paths = f.read().split('\n')[:-1]

    if not args.gpu:
        os.environ["CUDA_VISIBLE_DEVICES"] = "-1"

    # =========== preprocessing ===========
    # same as in train.py used for training

    feature = args.feature

    preprocess_kwargs = {
        'threshold': args.threshold,
        'downsample_1': 1,
        'downsample_2': 1,
        'shape': (224, 224, 1)
    }

    def preprocessor(PDFs):
        if args.remove_region_around_origin:
            return pp.remove_region_around_origin(pp.preprocess_2(PDFs, **preprocess_kwargs), removal_size=(args.frac_x_remove, args.frac_y_remove))
        else:
            return pp.preprocess_2(PDFs, **preprocess_kwargs)

    # =========== dataset split ===========

    train_test_split_kwargs = {
        'val_size': 0.1,
        'test_size': 0.1,
        'random_state': 1234,
        'random_state_validation': 1234,
    }

    train_test_split = partial(tu.regression_train_test_split_4, **train_test_split_kwargs)

    datasets = [AttoDataset(fn) for fn in datasets_paths]

    for ds in datasets:
        ds.preprocess(preprocessor, feature, delete_NPZ=False)

    if args.use_data_generator:
        def transform_X_fun(X, SL=1.0):
            X = dg.random_detector_saturation_tf(X,
                                                 saturation_level_min=SL,
                                                 saturation_level_max=1.0,
                                                 )
            X = dg.random_flip_lrud_tf(X)
            X = dg.random_contrast_tf(X, contrast_min=0.1, contrast_max=1.0)
            X = dg.random_brightness_tf(X, brightness_max_delta=1.0)
            X = tf.clip_by_value(X, -1, 1)
            return X

        def transform_y_fun(y):
            return y

        if not args.auto_saturation_level_min:
            def data_gen_fun(model_filename):
                return partial(dg.DataGenerator,  transform_X_fun=partial(transform_X_fun, SL=args.saturation_level_min),
                        transform_y_fun=transform_y_fun,
                        batch_size=8,
                        shuffle=True)
        else:
            def data_gen_fun(model_filename):
                def get_SL_from_filename(fn):
                    tab = fn.split('_')
                    SL = None
                    for i in range(len(tab)):
                        if tab[i] == 'SL':
                            SL = float(tab[i+1])
                    return SL

                SL = get_SL_from_filename(model_filename)
                print(f'for model {model_filename} using SL {SL}')
                return partial(dg.DataGenerator,  transform_X_fun=partial(transform_X_fun, SL=SL),
                        transform_y_fun=transform_y_fun,
                        batch_size=8,
                        shuffle=True)

    else:
        data_gen_fun = None

    models = glob.glob(args.models_path)
    print('Models to analyze:')
    print(models)

    grid, unique_model_names, unique_train_dataset_names = eu.evaluation_grid(models, datasets,
                                                                              batch_size=args.batch_size,
                                                                              use_data_generator=args.use_data_generator,
                                                                              train_test_split=train_test_split,
                                                                              predict_on_training_data=(not args.only_test),
                                                                              data_gen_fun=data_gen_fun,
                                                                              num_data_gen_realizations=args.num_data_gen_realizations)

    unique_eval_dataset_names = []
    for _, v in grid.items():
        for _, vv in v.items():
            for n, _ in vv.items():
                if n not in unique_eval_dataset_names:
                    unique_eval_dataset_names.append(n)

    with open(args.output_pickle, 'wb') as f:
        pickle.dump((grid, unique_model_names,
                     unique_train_dataset_names,
                     unique_eval_dataset_names), f)
        print(f'Analysis saved to {args.output_pickle}.')

    if args.save_plot:
        fig, axs = eu.plot_evaluation_grid(grid,
                                           unique_model_names,
                                           unique_train_dataset_names,
                                           eval_dataset_names=unique_eval_dataset_names,
                                           subplot_kwargs={'sharex': True, 'sharey': True, 'figsize': (12, 12), },
                                           color_list=None,
                                           marker_list=None,
                                           plot_single_model_number=None,
                                           max_points_per_dataset=10000,
                                           suptitle=args.models_path,
                                           parse_dataset_name_fun=lambda x: x)
        fig.savefig(args.output_pickle + '__gridplot.pdf', bbox_inches='tight')
        print(f'Plot saved to {args.output_pickle}__gridplot.pdf.')


#!/usr/bin/env python3
"""Solar Power Monitor built around a INA3221"""
import datetime
import json
import sched
import smbus
import time
import struct
import sys

class INA3221():
    """Driver class for interfacing to a Texas Instruments INA3221 Voltage and Current Monitor
    """

    INA3221_ADDRESS = 0x40 # A0+A1=GND

    INA3221_REG_CONFIG           = 0x00
    INA3221_REG_SHUNTVOLTAGE_1   = 0x01
    INA3221_REG_BUSVOLTAGE_1     = 0x02
    INA3221_REG_SHUNTVOLTAGE_SUM = 0x0d

    INA3221_CONFIG_RST      = (1<<15)
    INA3221_CONFIG_CH1_EN   = (1<<14)
    INA3221_CONFIG_CH2_EN   = (1<<13)
    INA3221_CONFIG_CH3_EN   = (1<<12)
    INA3221_CONFIG_AVG2     = (1<<11)
    INA3221_CONFIG_AVG1     = (1<<10)
    INA3221_CONFIG_AVG0     = (1<< 9)
    INA3221_CONFIG_VBUS_CT2 = (1<< 8)
    INA3221_CONFIG_VBUS_CT1 = (1<< 7)
    INA3221_CONFIG_VBUS_CT0 = (1<< 6)
    INA3221_CONFIG_VSH_CT2  = (1<< 5)
    INA3221_CONFIG_VSH_CT1  = (1<< 4)
    INA3221_CONFIG_VSH_CT0  = (1<< 3)
    INA3221_CONFIG_MODE_2   = (1<< 2)
    INA3221_CONFIG_MODE_1   = (1<< 1)
    INA3221_CONFIG_MODE_0   = (1<< 0)

    _VOLTAGE_LUT = { 'bus':   {'reg_base': INA3221_REG_BUSVOLTAGE_1,   'convert': lambda x: x/1000},
                     'shunt': {'reg_base': INA3221_REG_SHUNTVOLTAGE_1, 'convert': lambda x: x/1000/2/10} }

    SHUNT_RESISTOR_DEFAULT = 0.1

    def __init__(self, twi=1, addr=INA3221_ADDRESS, shunt_resistor=SHUNT_RESISTOR_DEFAULT):
        self._bus = smbus.SMBus(twi)
        self._addr = addr
        self._shunt_resistor = shunt_resistor

        # Always reset
        self._write_register(self.INA3221_REG_CONFIG, self.INA3221_CONFIG_RST)
        while self._read_register(self.INA3221_REG_CONFIG) & self.INA3221_CONFIG_RST: time.sleep(0)

        config = self.INA3221_CONFIG_CH1_EN | \
                 self.INA3221_CONFIG_CH2_EN | \
                 self.INA3221_CONFIG_CH3_EN | \
                 self.INA3221_CONFIG_AVG2 | \
                 self.INA3221_CONFIG_AVG1 | \
                 self.INA3221_CONFIG_AVG0 | \
                 self.INA3221_CONFIG_VBUS_CT2 | \
                 self.INA3221_CONFIG_VBUS_CT1 | \
                 self.INA3221_CONFIG_VBUS_CT0 | \
                 self.INA3221_CONFIG_VSH_CT2 | \
                 self.INA3221_CONFIG_MODE_2 | \
                 self.INA3221_CONFIG_MODE_1 | \
                 self.INA3221_CONFIG_MODE_0

        self._write_register(self.INA3221_REG_CONFIG, config)

        # Spin upto ~10ms first conversion is complete for all channels, no
        # other way to tell config is complete.  Prevents the first reading
        # from returning all zeros.
        timeout = 10
        while not all((self.get_voltage(i) and self.get_current(i)) for i in range(3)) and timeout > 0:
            time.sleep(0.001)
            timeout -= 1

    def _read_register(self, reg):
        data = self._bus.read_word_data(self._addr, reg).to_bytes(2, byteorder='big')
        return struct.unpack('H', data)[0]

    def _write_register(self, reg, data):
        swap = int.from_bytes(struct.pack('H', data), byteorder='big')
        return self._bus.write_word_data(self._addr, reg, swap)

    def get_voltage(self, ch, reg_type = 'bus'):
        """Get voltage for given channel in volts"""
        if ch < 0 or ch > 2:
            raise ValueError('Invalid channel')
        lut = self._VOLTAGE_LUT[reg_type]
        reg = lut['reg_base'] + ch * 2
        value = self._read_register(reg)
        value = (value - 65536) if value > 32767 else value
        return lut['convert'](value)

    def get_current(self, ch):
        return self.get_voltage(ch, 'shunt') / self._shunt_resistor * 100

class SolarPower():
    """Solar power monitor to monitor a SY-M150-14.6 + LiFePo4 battery + 25W solar panel"""
    _CH_LUT = {
            'solar':   {'ch': 0, 'gain': -1},
            'battery': {'ch': 1, 'gain': -1},
            'output':  {'ch': 2, 'gain':  1}
            }

    def __init__(self, scheduler, period=1, mean_period_cnt=30):
        self._sample_period = period
        self._mean_period_cnt = mean_period_cnt
        self._scheduler = scheduler
        self._ina3221 = INA3221()
        self._samples = []

        with open('/etc/machine-id') as fp:
            self._machine_id = fp.read().strip()

    def _read_channel(self, ch_dict):
        ch = ch_dict['ch']
        gain = ch_dict['gain']
        d = { 'v_load':  self._ina3221.get_voltage(ch, 'bus'),
              'current': self._ina3221.get_current(ch) / 1000 * gain
            }
        # Not sure how this is useful:
        #'v_shunt': self._ina3221.get_voltage(ch, 'shunt')
        return d

    def _get_system(self):
        d = {}
        try:
            with open('/sys/class/hwmon/hwmon0/temp1_input', 'r') as fp:
                # Get cpu temp in milli-degrees and convert to degrees
                d['cpu_temp'] = int(fp.read().strip())/1000.0
        except Exception as e:
            print(f"Failed to read CPU temp {e}", file=sys.stderr)

        return d

    def _sample_cb(self):
        d = { k: self._read_channel(v) for k, v in self._CH_LUT.items() }
        d['@machine_id'] = self._machine_id
        d['@time'] = datetime.datetime.now(datetime.timezone.utc).isoformat(timespec='seconds')
        d['system'] = self._get_system()

        #print(json.dumps(d))
        #print(json.dumps({'sample': d['@time']}))

        self._next_sample += self._sample_period
        s.enterabs(self._next_sample, 1, self._sample_cb)

        self._samples += [d]
        if len(self._samples) >= self._mean_period_cnt:
            s.enter(0, 0, self._calc_mean_cb)

    def _get_ch_means(self, name):
        cnt = len(self._samples)
        field_names = self._samples[0][name].keys()
        # Function to yield every sample from a given field
        field_gen = lambda field: (sample[name][field] for sample in self._samples)
        # Return dictionary with the mean of each field
        return { f: sum(field_gen(f))/cnt for f in field_names}

    def _calc_mean_cb(self):
        d = { '@machine_id': self._machine_id,
              '@time': datetime.datetime.now(datetime.timezone.utc).isoformat(timespec='seconds') }

        names = tuple(filter(lambda x: not x.startswith('@'), self._samples[0].keys()))
        d.update({n: self._get_ch_means(n) for n in names})

        print(json.dumps(d))
        self._samples.clear()

    def start(self):
        self._next_sample = time.monotonic()
        self._sample_cb()

if __name__ == '__main__':
    import argparse

    s = sched.scheduler()

    parser = argparse.ArgumentParser()
    parser.add_argument("--period_cnt", help="period to summarize and emit", type=int, default=30)
    args = parser.parse_args()

    sp = SolarPower(s, mean_period_cnt=args.period_cnt)
    sp.start()

    s.run()


#!/usr/bin/python
# -*- coding: UTF-8 -*-
import Queue1
import EdgeWeightedDigraph
import EdgeWeightedDirectedCycle
import Stack1

class BellmanFordSP(object):

    def __init__(self,G,s):
        self.distTo = [0.0]*G.V()
        self.edgeTo = [0]*G.V()
        self.onQueue = [False]*G.V()
        for v in range(G.V()):
            self.distTo[v] = float("inf")
        self.distTo[0] = 0.0
        self.queue = Queue1()
        self.queue.enqueue(s)
        self.onQueue[s] = True
        self.cost = 0
        self.cycle = Stack1()
        while (not self.queue.isEmpty() and not self.hasNegativeCycle()):
            v = self.queue.dequeue()
            self.onQueue[v] = False
            self.relax(G,v)

    def relax(self,G,v):
        for e in G.adj(v):
            w = e.to()
            if self.distTo[w] > self.distTo[v] + e.weight():
                self.distTo[w] = self.distTo[v] + e.weight()
                self.edgeTo[w] = e
                if not self.onQueue[w]:
                    self.queue.enqueue(w)  # Bellman算法就是对边任意的进行放松总能得到最短路径
                    self.onQueue[w] = True
            if self.cost%G.V() == 0:
                self.cost += 1
                self.findNegativeCycle()
                if self.hasNegativeCycle():
                    return

    def hasNegativeCycle(self):
        return self.cycle

    def findNegativeCycle(self):
        V = len(self.edgeTo)
        spt = EdgeWeightedDigraph(V)
        for v in range(V):
            if self.edgeTo[v] != None:
                spt.addEdge(self.edgeTo[v])
        finder = EdgeWeightedDirectedCycle(spt)
        self.cycle = finder.cycle()

    def distTo(self,v):
        return self.distTo[v]

    def hasPathTo(self,v):
        return self.distTo[v]<float("INF")

    def pathTo(self,v):
        if not self.hasPathTo(v):
            return None
        path = Stack1()
        e = self.edgeTo[v]
        while not e == None:
            path.push(e)
            e = self.edgeTo[e.from1()]
        return path


import pyrogram
import httpx

from defs.glover import api_id, api_hash, logtail_token
from scheduler import scheduler
from logging import getLogger, INFO, ERROR, StreamHandler, basicConfig, FileHandler, Formatter
from coloredlogs import ColoredFormatter
from logtail import LogtailHandler

# Enable logging
logs = getLogger("T2G")
logging_format = "%(levelname)s [%(asctime)s] [%(name)s] %(message)s"
logging_handler = StreamHandler()
logging_handler.setFormatter(ColoredFormatter(logging_format))
file_handler = FileHandler("log.txt", mode="w", encoding="utf-8")
file_handler.setFormatter(Formatter(logging_format))
logtail_handler = LogtailHandler(source_token=logtail_token)
root_logger = getLogger()
root_logger.setLevel(ERROR)
root_logger.addHandler(logging_handler)
root_logger.addHandler(file_handler)
if logtail_token:
    root_logger.addHandler(logtail_handler)
basicConfig(level=INFO)
logs.setLevel(INFO)

if not scheduler.running:
    scheduler.start()

bot = pyrogram.Client(
    "bot", api_id=api_id, api_hash=api_hash, plugins=dict(root="plugins")
)
headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.72 Safari/537.36"
}
request = httpx.AsyncClient(timeout=60.0, headers=headers)


"""
File_id: 07oct2021_menu
Related file id:  07oct2021_async_client, 07oct2021_async_server
This is the alpha player menu code for the "shooter" game
"""
import time
from sys import exit
from threading import Thread
from pygame_menu.locals import *
from typing import Optional
from logging import handlers
import logging
import coloredlogs
import queue
import pygame
import pygame_menu
import asyncio
import async_client
import pygame.freetype as ft
import csv
import role_def
import game_class_c
from platform_shooter_settings import *

background_image = pygame.image.load("resources/gui/ui.png")

COVER_PAGE_BGIMG = pygame_menu.BaseImage("resources/gui/ui.png")
CREDITS_BGIMG = pygame_menu.BaseImage("resources/gui/credits_screen.png")
JOIN_BGIMG = pygame_menu.BaseImage("resources/gui/character_selection.png")
CONN_SETTING_BGIMG = pygame_menu.BaseImage("resources/gui/connection_settings.png")
WAITING_BGIMG = pygame_menu.BaseImage("resources/gui/waiting.png")
WAITING_BGIMG_SURF = pygame.image.load("resources/gui/waiting.png")
font_file_OvOV20 = "resources/OvOV20.ttf"
btn_img_rgt = pygame_menu.BaseImage("resources/gui/right.png")
btn_img_rgt_prsd = pygame_menu.BaseImage("resources/gui/right_pressed.png")
btn_img_lft = pygame_menu.BaseImage("resources/gui/right.png").flip(True, False)
btn_img_lft_prsd = pygame_menu.BaseImage("resources/gui/right_pressed.png").flip(True, False)
btn_img_ok = pygame_menu.BaseImage("resources/gui/Button_18_small.png")
btn_img_play = pygame_menu.BaseImage("resources/gui/play.png")
btn_img_credits = pygame_menu.BaseImage("resources/gui/credits.png")

GIRL_idle_img = []
for i in range(9):
    GIRL_idle_img.append(pygame_menu.BaseImage(f"resources/gui/girl/Idle__00{i}.png"))
BOY_idle_img = []
for i in range(9):
    BOY_idle_img.append(pygame_menu.BaseImage(f"resources/gui/boy/Idle__00{i}.png"))

# -----------------------------------------------------------------------------
# Methods

class DrawText(pygame.sprite.Sprite):
    def __init__(self, text):
        super().__init__()
        self.text = text
        self.font = pygame.font.Font("resources/OvOV20.ttf", 30)
        self.image = self.font.render(text, True, (255, 255, 255))
        self.rect = self.image.get_rect()
        self.rect.x = 100
        self.rect.y = 100
        self.change_x = 0
        self.change_y = 0
        self.speed = 6

    def update(self) -> None:
        self.rect.x += self.change_x
        self.rect.y += self.change_y
        self.image = self.font.render(self.text, True, (255, 255, 255))

    def go_left(self):
        self.change_x = -self.speed

    def go_right(self):
        self.change_x = self.speed

    def go_up(self):
        self.change_y = -self.speed

    def go_down(self):
        self.change_y = self.speed

    def stop(self):
        self.change_x = 0
        self.change_y = 0

    def pos(self):
        return self.rect.x, self.rect.y

class EventLoop(Thread):
    def __init__(self):
        self._loop = asyncio.new_event_loop()
        super().__init__(target=self._loop.run_forever, daemon=True)
        self.start()
        self.game_task = None

    def stop(self):
        self._loop.call_soon_threadsafe(self._loop.stop)

    def stop_tasks(self):
        for task in asyncio.tasks.all_tasks(self._loop):
            self._loop.call_soon_threadsafe(task.cancel)
            done = False
            while not done:
                done = task.done()

    def create_task(self, coro):
        self.game_task = asyncio.run_coroutine_threadsafe(coro, self._loop)
        return self.game_task

class MyLogger:
    def __init__(self):
        FIELD_STYLES = {'asctime': {'color': 'green'},
                        'levelname': {'bold': False, 'color': (200, 200, 200)},
                        'filename': {'color': 'cyan'},
                        'funcName': {'color': 'blue'}}

        LEVEL_STYLES = {'critical': {'bold': True, 'color': 'red'},
                        'debug': {'color': 'magenta'},
                        'error': {'color': 'red'},
                        'exception': {'color': 'red'},
                        'info': {'color': 'green'},
                        'warning': {'color': 'yellow'}}

        self.my_logger = logging.getLogger()

        format = '%(asctime)s [%(levelname)s] - %(message)s'

        coloredlogs.install(level=logging.INFO,
                            logger=self.my_logger,
                            fmt=format,
                            field_styles=FIELD_STYLES,
                            level_styles=LEVEL_STYLES)

        format_str = logging.Formatter(format)
        fh = handlers.RotatingFileHandler("client_log.txt", "a", 100000, 3)
        fh.setFormatter(format_str)
        # self.my_logger.addHandler(fh)

class Menu:
    def __init__(self):
        pygame.init()
        self.playing = True
        self.running = True
        self.winner = ""
        self.reselect_flag = False
        self.reselect_done_flag = False
        self.my_logger = MyLogger()
        self.clock = pygame.time.Clock()
        self.screen = pygame.display.set_mode(WINDOW_SIZE)  # , flags=pygame.NOFRAME)
        self.room_selected1 = "Join an existing game: "
        self.room_selected2 = "<click to choose>"
        self.t_loop = EventLoop()
        self.connection: Optional[async_client.Network] = None
        self.connected_flag = False
        self.server_ip = "47.94.100.39"
        self.server_port = "8887"
        self.my_name = ""
        self.game_rooms = [("No game", False, 1), ]  # [[player0_name, game_ready, room_id],]
        self.chosen_room: None  # [player0_name, game_ready, room_id], same as dropselect item
        self.room_frame = None
        self.conn_type = "handshake"  # "create" or "join"
        self.client_id = "0"
        self.your_name = ""
        self.map_id = 0
        self.match_id = 0
        self.level_id = 0
        self.role_id = 0
        self.player_id = 0
        # self.credits = self.read_csv("resources/credits.csv")
        self.credits = role_def.game_credits
        self.credits_speed = 0.1
        self.credits_x = 0
        self.credits_y00 = 380
        self.credits_y0 = self.credits_y00
        self.credits_pitch = 35
        self.credits_cnt = len(self.credits)
        self.credits_timer = 0
        # self.credits_on_flg = False
        # self.credits_timer_up = 2000
        # self.credits_timing_flg = False
        self.gs_lst = []  # Game state received as a list
        self.splat_font = ft.Font("resources/fonts/earwig factory rg.ttf", 60)
        self.counting_font = ft.Font(font_file_OvOV20, 60)
        self.amy_font_file1 = self.font = "resources/OvOV20.ttf"
        self.main_menu: [pygame_menu.menu] = None
        self.b_connect: [pygame_menu.widgets.widget.button] = None
        self.selector_game: [pygame_menu.widgets.widget.dropselect] = None
        self.surface: [pygame.Surface] = pygame.image.load("resources/gui/Window_06.png")
        # self.surface: [pygame.Surface] = pygame.image.load("resources/gui/ui.png")
        self.sound: [pygame_menu.sound.Sound] = None
        self.game_over_screen_flag = True

        self.idle_img_frame_rate = 4  # 1/4 of FPS

        girl_idle = []
        girl_idle_50per = []

        # for j in range(9):
        #     girl_idle.append(pygame.image.load(f"resources/gui/girl/Idle__00{j}.png"))
        #     girl_idle_50per.append(pygame.image.load(f"resources/gui/girl/50 percent/Idle__00{j}.png"))

        girl_idle = []  # test Amy's art
        for j in range(5):
            img = pygame.image.load(f"resources/gui/girl/aIdle__00{j}.png")
            # girl_idle.append(pygame.transform.scale2x(img))
            girl_idle.append(img)

        boy_idle = []
        boy_idle_50per = []

        # for j in range(9):
            # boy_idle.append(pygame.image.load(f"resources/gui/boy/Idle__00{j}.png"))
            # boy_idle_50per.append(pygame.image.load(f"resources/gui/boy/50 percent/Idle__00{j}.png"))

        boy_idle = []  # test Amy's art
        for j in range(4):
            # img = pygame.image.load(f"resources/gui/boy/aIdle__00{j}.png")
            img = pygame.image.load(f"resources/gui/boy/{j}.png")
            # girl_idle.append(pygame.transform.scale2x(img))
            boy_idle.append(img)

        self.img_lst = [boy_idle, girl_idle]
        self.img_lst_50per = [boy_idle_50per, girl_idle_50per]

        self.current_role_id = 0
        self.previous_role_id = 1
        self.current_img_lst = self.img_lst[self.current_role_id]

        self.girl_desc_lbl_lst = []
        self.boy_desc_lbl_lst = []

        self.lbl_lst = [self.boy_desc_lbl_lst, self.girl_desc_lbl_lst]

        self.msg_lbl = None
        self.check_join_back_btn = None
        self.check_join_ok_btn = None

        self.btn_img_rgt_prsd = pygame_menu.BaseImage("resources/gui/right_pressed.png")
        self.btn_img_rgt_prsd.scale4x()

        self.lcls = locals()

    def read_csv(self, file_name, dict=0):
        result = None
        if dict == 0:
            with open(file_name, newline='') as csvfile:
                reader = csv.reader(csvfile)
                result = []
                for item in reader:
                    result.append(item[0])
        elif dict == 1:
            with open(file_name, newline='') as csvfile:
                reader = csv.DictReader(csvfile)
                for item in reader:
                    print(item)
        return result

    def cb_conn_conn(self, server_ip, server_port, player_name, **kwargs):
        if not self.connected_flag:
            self.connected_flag = True
        else:
            kwargs["widget"].set_title(f"Connection status: already connected with client id - {self.client_id}")
            return
        self.server_ip = server_ip.get_value()
        self.server_port = server_port.get_value()
        self.my_name = player_name.get_value()
        pygame.display.set_caption(f"{self.my_name}'s Game Window")
        self.connection = async_client.Network(self.server_ip, self.server_port)
        conn_result = self.t_loop.create_task(self.connection.conn(self.my_name))
        try:
            # this connection should be established immediately otherwise there's a network issue
            conn_result.result(TIMEOUT)
            self.client_id = self.connection.client_id
        except Exception as e:
            kwargs["widget"].set_title(f"Connection status: error - {e}")
            self.my_logger.my_logger.error(f"Connection status: error - {e}")
        else:
            kwargs["widget"].set_title(f"Connection status: connected with client id - {self.client_id}")
            self.my_logger.my_logger.info(f"Connected to server: {self.server_ip}:{self.server_port} "
                                          f"with client id - {self.client_id}")

    def cb_conn_create(self):
        self.conn_type = "create"
        self.t_loop.create_task(self.connection.create())
        self.t_loop.create_task(self.connection.client())
        self.demo_game()

    def cb_selection0_menu_opened(self, from_menu, to_menu):
        self.conn_type = "create"
        self.t_loop.create_task(self.connection.create())
        self.t_loop.create_task(self.connection.client_game())

    def cb_play(self):
        self.demo_game()

    def conn_join(self):
        task = self.t_loop.create_task(self.connection.join())
        try:
            # this connection should be established immediately otherwise there's a network issue
            task.result(TIMEOUT)
            self.game_rooms = self.connection.game_rooms
            self.game_rooms = [tuple(lst) for lst in self.game_rooms]
            self.selector_game.update_items(self.game_rooms)
            self.selector_game.set_default_value(0)
            self.selector_game.reset_value()
            self.chosen_room = self.selector_game.get_items()[0]  # Default choice is the first game room
        except Exception as e:
            self.my_logger.my_logger.error(f"Connection issue during joining - {e}")

    def cb_role_sel_lft(self, **kwargs):
        self.previous_role_id = self.current_role_id
        kwargs["widget"].set_background_color(btn_img_lft_prsd)
        self.current_role_id = (self.current_role_id - 1) % len(self.img_lst)

        # if self.current_role_id - 1 < 0:
        #     self.current_role_id = len(self.img_lst) - 1
        # else:
        #     self.current_role_id -= 1

        current_lbl_lst = self.lbl_lst[self.current_role_id]
        previous_lbl_lst = self.lbl_lst[self.previous_role_id]

        for j in range(len(current_lbl_lst)):
            current_lbl_lst[j].show()
            previous_lbl_lst[j].hide()

        # self.previous_role_id = self.current_role_id

        self.current_img_lst = self.img_lst[self.current_role_id]

    def cb_role_sel_rgt(self, **kwargs):
        kwargs["widget"].set_background_color(btn_img_rgt_prsd)
        self.previous_role_id = self.current_role_id
        self.current_role_id = (self.current_role_id + 1) % len(self.img_lst)
        # if self.current_role_id + 1 == len(self.img_lst):
        #     self.current_role_id = 0
        # else:
        #     self.current_role_id += 1

        # current_lbl_lst = self.lbl_lst[self.current_role_id]
        current_lbl_lst = self.lbl_lst[self.current_role_id]
        previous_lbl_lst = self.lbl_lst[self.previous_role_id]

        for j in range(len(current_lbl_lst)):
            current_lbl_lst[j].show()
            previous_lbl_lst[j].hide()

        self.current_img_lst = self.img_lst[self.current_role_id]

    # def cb_join_game_btn(self):
    #     self.t_loop.create_task(self.connection.send_room_choice(self.chosen_room))
    #     self.t_loop.create_task(self.connection.client_game())
    # self.demo_game()

    def cb_btn_mouseleave(self, widget: pygame_menu.widgets.Button, event):
        dir = widget.get_attribute("direction")
        if dir == "r":
            widget.set_background_color(btn_img_rgt)
        elif dir == "l":
            widget.set_background_color(btn_img_lft)

    def cb_dropselector_game_onchange(self, item_index: tuple, game_ready, room_id):
        # [(player0_name, game_ready, room_id),]
        self.chosen_room = item_index[0]

    def cb_join_game_menu_openned(self, from_menu, to_menu):
        self.player_id = 1
        self.conn_join()

    def cb_refresh(self):
        # self.game_rooms
        task = self.t_loop.create_task(self.connection.refresh())
        try:
            # this connection should be established immediately otherwise there's a network issue
            task.result(TIMEOUT)
            self.game_rooms = self.connection.game_rooms
            self.game_rooms = [tuple(lst) for lst in self.game_rooms]
            self.selector_game.update_items(self.game_rooms)
            self.selector_game.set_default_value(0)
            self.selector_game.reset_value()
            self.chosen_room = self.game_rooms[0]
            # self.selector_game.render()
        except asyncio.TimeoutError:
            self.my_logger.my_logger.error(f"Connection issue to server during refreshing")

    def cb_selector_map_onchange(self, item_tuple, *args, **kwargs):
        self.map_id = item_tuple[1]

    def cb_selector_match_type_onchange(self, item_tuple, *args, **kwargs):
        self.match_id = item_tuple[1]

    def cb_check_join_menu_openned(self, from_menu, to_menu):
        if not self.reselect_flag:
            self.t_loop.create_task(self.connection.send_room_choice(self.chosen_room, self.current_role_id))
            try:
                msg = self.connection.chosen_room_ok.get(timeout=TIMEOUT)
                if msg == "ok":
                    self.msg_lbl.set_title("Game room choice accepted, press ok to proceed")
                    self.check_join_back_btn.hide()
                    self.check_join_ok_btn.show()
                else:
                    self.msg_lbl.set_title("Game room choice is not accepted, please choose again")
                    self.check_join_back_btn.show()
                    self.check_join_ok_btn.hide()
            except queue.Empty:
                # TODO: code to acknowledge the player and ask for input
                print("Connection issue")
                self.end()
        else:
            self.connection.game_setting = [1, self.current_role_id, 0, 0]
            self.reselect_done_flag = True
            self.msg_lbl.set_title("Good choice, press ok to proceed")
            self.check_join_back_btn.hide()
            self.check_join_ok_btn.show()

    def cb_player0_wait_menu_opened(self, from_menu, to_menu):
        self.player_id = 0
        self.connection.game_setting = [1, self.map_id, self.match_id, self.current_role_id]
        # self.t_loop.create_task(self.connection.client_game())
        if not self.reselect_flag:  # if reselect, self.play() is already running
            self.play()
            # self.reselect_flag = True
        else:
            self.reselect_done_flag = True

    def cb_player1_wait_menu_opened(self, from_menu, to_menu):
        # self.t_loop.create_task(self.connection.send_room_choice(self.chosen_room))
        self.t_loop.create_task(self.connection.client_game())

        self.play()

    def cb_pass(self, from_menu, to_menu):
        pass

    def cb_animate_credits(self, widget: 'pygame_menu.widgets.Widget', menu: 'pygame_menu.Menu'):
        id_str = widget.get_id()
        pos_x = widget.get_rect()[0]
        pos_y = widget.get_position()[1]
        if id_str == str(self.credits_cnt - 1):  # index of the last element is len()-1
            if pos_y < -10:
                self.credits_y0 = self.credits_y00
        else:
            # self.credits_y0 += self.credits_speed
            self.credits_y0 -= self.credits_speed
        # widget.translate(self.credits_x, self.credits_y0 + int(id_str) * self.credits_pitch)
        widget.translate(pos_x, self.credits_y0 + int(id_str) * self.credits_pitch)

    def cb_selection0_img_anim(self, widget: pygame_menu.widgets.widget.image, menu):
        pass

    def cb_rgt_btn_pressed(self, **kwargs):
        kwargs["widget"].set_background_color(self.btn_img_rgt_prsd)

    def cb_img_animate(self, widget: pygame_menu.widgets.SurfaceWidget, ref_menu: pygame_menu.Menu):
        img_lst_name = widget.get_id()
        img_lst = self.lcls[img_lst_name]
        new_idx = widget.get_counter_attribute("idx", 1)
        if new_idx >= (len(img_lst) - 1) * 4:
            new_idx = 0
            widget.set_attribute("idx", 0)
        widget.set_surface(img_lst[new_idx // 4])

    def check_end(self, events):
        for event in events:
            if event.type == pygame.QUIT or \
                    (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                # if self.connection is not None:
                #     self.connection.connected_flag = False
                self.end()
            if self.connection is not None:
                if not self.connection.connected_flag:
                    self.end()

    def end(self):
        self.t_loop.stop_tasks()
        self.t_loop.stop()
        # self.conn_issue_screen()
        pygame.quit()
        exit()

    def wait_screen(self):
        while not self.connection.game_ready:
            self.clock.tick(FPS)
            # self.screen.fill((0, 200, 0))
            self.screen.blit(WAITING_BGIMG_SURF, (0, 0))
            if self.player_id == 0:
                self.counting_font.render_to(self.screen, (220, 350), "Waiting for 2nd player")
            else:
                self.counting_font.render_to(self.screen, (220, 310), "Waiting for 1st player")
                self.counting_font.render_to(self.screen, (260, 380), "to set the game")

            events = pygame.event.get()
            self.check_end(events)
            pygame.display.flip()

    def reselect(self):
        if not game_class_c.running:
            self.end()
        """
        different from the flows for player1 in the first run cycle,
        self.t_loop.create_task(self.connection.client_game()) must be run for player1 at beginning of
        def reselect(self) so that the while loop in the reselect() method on server won't be blocked
        """
        self.t_loop.create_task(self.connection.client_game())
        self.winner = ""
        self.reselect_flag = True
        if self.player_id == 1:
            self.join_game_menu.set_onbeforeopen(self.cb_pass)
            self.selector_game.hide()
            self.b_refresh.hide()
            self.main_menu._current = self.join_game_menu
            self.main_menu.enable()
            img_idx = 0
            while not self.reselect_done_flag:
                self.clock.tick(FPS)

                events = pygame.event.get()
                self.check_end(events)

                self.main_menu.update(events)
                # self.join_game_menu.update(events)

                if self.main_menu.is_enabled():
                    self.screen.blit(background_image, (0, 0))
                    if self.main_menu.is_enabled():
                        self.main_menu.draw(self.screen)
                else:
                    break

                # img_idx = self.role_img_animation(img_idx)
                img_idx = self.role_img_animation(self.img_join_menu, img_idx)

                pygame.display.flip()

        elif self.player_id == 0:

            self.main_menu._current = self.sub_menu_selection0
            self.main_menu.enable()

            img_idx = 0
            while not self.reselect_done_flag:
                self.clock.tick(FPS)

                events = pygame.event.get()
                self.check_end(events)

                self.main_menu.update(events)
                # self.join_game_menu.update(events)

                if self.main_menu.is_enabled():
                    self.screen.blit(background_image, (0, 0))
                    if self.main_menu.is_enabled():
                        self.main_menu.draw(self.screen)
                else:
                    break

                # img_idx = self.role_img_animation(img_idx)
                img_idx = self.role_img_animation(self.img_selection0, img_idx)

                pygame.display.flip()

        self.reselect_done_flag = False

    def role_img_animation(self, img, img_idx):
        if img_idx + 1 >= len(self.current_img_lst) * 15:
            img_idx = 0
        else:
            img_idx += 1
        img.set_surface(self.current_img_lst[img_idx // 15])
        return img_idx

    def idle_img_animation(self, img, boy_girl, img_idx):
        # boy = 0, girl = 1
        if img_idx + 1 == len(self.img_lst[boy_girl]) * 3:
            img_idx = 0
        else:
            img_idx += 1
        img.set_surface(self.img_lst[boy_girl][img_idx // 3])
        return img_idx

    def idle_img_animation_50per(self, img, boy_girl, img_idx):
        # boy = 0, girl = 1
        if img_idx + 1 == len(self.img_lst_50per[boy_girl]) * 3:
            img_idx = 0
        else:
            img_idx += 1
        img.set_surface(self.img_lst_50per[boy_girl][img_idx // 3])
        return img_idx

    def conn_issue_screen(self):
        while True:
            self.clock.tick(FPS)
            events = pygame.event.get()
            # self.check_end(events)
            for event in events:
                if event.type == pygame.KEYDOWN:
                    break

            self.counting_font.render_to(self.screen, (110, 350), f"Connection issue", bgcolor=LIGHT_GREEN)
            self.counting_font.render_to(self.screen, (120, 400), f"Press any key to quit", bgcolor=LIGHT_GREEN)
            pygame.display.flip()

    def game_over_screen(self):
        if not game_class_c.running:
            self.end()
        counting = 2
        now = pygame.time.get_ticks()
        while self.game_over_screen_flag:
            self.clock.tick(FPS)
            events = pygame.event.get()
            self.check_end(events)

            if pygame.time.get_ticks() - now >= 1000 and counting > 0:
                now = pygame.time.get_ticks()
                counting -= 1
            if counting == 0:
                for event in events:
                    if event.type == pygame.KEYDOWN:
                        self.game_over_screen_flag = False
                        return

            self.counting_font.render_to(self.screen, (300, 350), f"{self.winner} wins!", bgcolor=LIGHT_GREEN)
            self.counting_font.render_to(self.screen, (20, 400), f"Press any key to continue in {counting} sec",
                                         bgcolor=LIGHT_GREEN)
            pygame.display.flip()

    def play(self):
        # g = game_class_c.GameSC(self.screen, SCREEN_WIDTH, SCREEN_HEIGHT,
        #                       self.map_id, self.match_id, self.player_id, self.role_id, self.my_name, self.your_name)
        while game_class_c.running and self.connection.connected_flag:
            self.game()
            self.game_over_screen()
            self.reselect()
        pygame.quit()
        exit()

    def game(self):
        self.main_menu.disable()
        self.wait_screen()
        # self.main_menu.disable()

        role_ids = (int(self.connection.server_msg[4]), int(self.connection.server_msg[5]))
        self.role_id = role_ids[self.player_id]
        game_type = game_class_c.game_type_lst[role_ids[0] + role_ids[1]]

        g = game_type(self.screen, SCREEN_WIDTH, SCREEN_HEIGHT,
                      self.map_id, self.match_id, self.player_id, self.role_id, self.my_name, self.your_name)

        g.your_name = self.connection.server_msg[1]
        # g.map_id = self.connection.server_msg[2]
        g.current_level_no = int(self.connection.server_msg[2])
        g.match_id = int(self.connection.server_msg[3])
        # g.role_id = int(self.connection.server_msg[4])

        g.new()

        while g.playing:  # routine game tick
            g.events()
            self.connection.events_str.put(g.events_str)
            try:
                self.gs_lst = self.connection.game_state.get(timeout=TIMEOUT)
                # self.gs_lst = self.connection.game_state.get()
            except queue.Empty:
                # self.connection.game_ready = False
                # self.conn_issue_screen()
                print("Connection issue")
                self.end()

            g.update_game_state(self.gs_lst)
            g.draw()

        self.connection.game_ready = False
        self.connection.game_setting[0] = 0
        self.game_over_screen_flag = True
        self.winner = g.winner
        while self.connection.client_game_flag:
            # waiting for connection.client_game() to return
            # True: not returned, False: returned
            self.clock.tick(FPS)
            pygame.display.flip()

    def demo_game(self):
        self.main_menu.disable()

        player_disconnected_flag = False  # if the other player is disconnected, this will be set to True
        my_msg = DrawText("My msg:")
        their_msg = DrawText(f"{self.connection.server_msg}")
        msg_grp = pygame.sprite.Group()
        msg_grp.add(my_msg, their_msg)
        while True:
            self.clock.tick(FPS)
            self.screen.fill((0, 200, 0))

            events = pygame.event.get()
            self.check_end()

            for event in events:
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        self.connection.pos_send[0] += 1
                        self.connection.pos_send[1] += 1
                    if event.key == pygame.K_LEFT:
                        my_msg.go_left()
                    if event.key == pygame.K_RIGHT:
                        my_msg.go_right()
                    if event.key == pygame.K_UP:
                        my_msg.go_up()
                    if event.key == pygame.K_DOWN:
                        my_msg.go_down()
                if event.type == pygame.KEYUP:
                    my_msg.stop()

            if self.connection.server_msg[0] != "Game Ready":
                my_msg.rect.x, my_msg.rect.y = (100, 100)
                their_msg.rect.x, their_msg.rect.y = (100, 200)
            elif not player_disconnected_flag:
                try:
                    # 3 lines of get_nowait() to make sure even the Queue() is full, only the last item is returned
                    their_msg.rect.x, their_msg.rect.y = self.connection.pos_recv.get_nowait()
                    their_msg.rect.x, their_msg.rect.y = self.connection.pos_recv.get_nowait()
                    their_msg.rect.x, their_msg.rect.y = self.connection.pos_recv.get_nowait()
                except queue.Empty:
                    pass
            else:
                their_msg.rect.x, their_msg.rect.y = (200, 200)

            my_msg.text = f"{self.my_name}'s client {self.connection.client_id}, {str((my_msg.rect.x, my_msg.rect.y))}"
            if their_msg.rect.x == their_msg.rect.y == -99:
                player_disconnected_flag = True

            if player_disconnected_flag:
                their_msg.text = f"Player '{self.connection.opponent_name}' is disconnected from the server"
            else:
                their_msg.text = f"{self.connection.server_msg[1]}, {str((their_msg.rect.x, their_msg.rect.y))}"

            self.connection.pos_send = my_msg.pos()

            msg_grp.update()
            msg_grp.draw(self.screen)

            pygame.display.flip()

    def main(self, test: bool = False) -> None:
        """
        Main program.
        :param test: Indicate function is being tested
        :return: None
        """

        all_sound = pygame_menu.sound.Sound()
        # engine.set_sound(pygame_menu.sound.SOUND_TYPE_CLICK_MOUSE, 'resources/sound/Designer_Stubble.ogg', volume=0.5)
        all_sound.set_sound(pygame_menu.sound.SOUND_TYPE_OPEN_MENU, 'resources/sound/Amazon.ogg', volume=0.5)
        # all_sound.play_open_menu()
        # engine.play_click_mouse()

        engine = pygame_menu.sound.Sound()
        # engine.set_sound(pygame_menu.sound.SOUND_TYPE_CLICK_MOUSE, 'resources/sound/click.ogg')
        engine.set_sound(pygame_menu.sound.SOUND_TYPE_WIDGET_SELECTION, 'resources/sound/click.ogg')
        # engine.set_sound(pygame_menu.sound.SOUND_TYPE_OPEN_MENU, 'resources/sound/click.ogg')
        # engine.set_sound(pygame_menu.sound.SOUND_TYPE_OPEN_MENU, '/home/me/open.ogg')

        # self.sub_menu_selection0.set_sound(engine, recursive=True)  # Apply on menu and all sub-menus

        # btn_img_lft = pygame_menu.BaseImage("resources/gui/left.png")
        # btn_img_lft.scale4x()
        # btn_img_rgt = pygame_menu.BaseImage("resources/gui/right.png")
        # btn_img_rgt.scale4x()
        # btn_img_rgt_prsd = pygame_menu.BaseImage("resources/gui/right_pressed.png")
        # btn_img_rgt_prsd.scale4x()

        # -------------------------------------------------------------------------
        # Create menus: Main menu
        # -------------------------------------------------------------------------
        no_title_theme = pygame_menu.themes.THEME_ORANGE.copy()
        # no_title_theme.title_background_color = (0, 0, 0, 0)
        no_title_theme.background_color = COVER_PAGE_BGIMG
        # no_title_theme.title_font = pygame_menu.font.FONT_8BIT
        #
        # no_title_theme.title_font_shadow = True
        # no_title_theme.title_font_color = (200, 50, 50)
        # no_title_theme.title_close_button = False
        # no_title_theme.title_offset = (120, 0)

        # no_title_theme.background_color = (0, 0, 0, 10)
        no_title_theme.title = False
        # no_title_theme.widget_font = pygame_menu.font.FONT_MUNRO
        no_title_theme.widget_font = self.amy_font_file1
        no_title_theme.widget_alignment = pygame_menu.locals.ALIGN_LEFT
        no_title_theme.title_bar_style = pygame_menu.widgets.MENUBAR_STYLE_NONE
        no_title_theme.widget_padding = 15

        credits_theme = no_title_theme.copy()
        credits_theme.background_color = CREDITS_BGIMG
        credits_theme.widget_font_color = CREDITS_COLOR
        credits_theme_font = pygame.font.Font(credits_theme.widget_font, credits_theme.widget_font_size)

        no_title_theme_join_game = no_title_theme.copy()
        no_title_theme_join_game.background_color = JOIN_BGIMG

        no_title_theme_waiting = no_title_theme.copy()
        no_title_theme_waiting.background_color = WAITING_BGIMG
        no_title_theme_waiting.widget_alignment = pygame_menu.locals.ALIGN_CENTER

        connection_setting_theme = no_title_theme.copy()
        connection_setting_theme.background_color = CONN_SETTING_BGIMG
        connection_setting_theme.widget_offset = (70, 100)

        sub_menu_selection0_theme = no_title_theme.copy()
        sub_menu_selection0_theme.background_color = JOIN_BGIMG

        # self.button_effect0 = pygame_menu.widgets.HighlightSelection()

        self.main_menu = pygame_menu.Menu(
            "Platform Game", WINDOW_SIZE[0], WINDOW_SIZE[1],
            center_content=False,
            onclose=pygame_menu.events.EXIT,  # User press ESC button
            theme=no_title_theme,
            position=[40, 20],
        )

        self.credits_menu = pygame_menu.Menu(
            "CREDITS", WINDOW_SIZE[0], WINDOW_SIZE[1],
            center_content=False,
            onclose=pygame_menu.events.EXIT,  # User press ESC button
            theme=credits_theme,
            position=[40, 20],
        )

        self.connection_menu = pygame_menu.Menu(
            "Platform Game", WINDOW_SIZE[0], WINDOW_SIZE[1],
            center_content=False,
            # onclose=pygame_menu.events.EXIT,  # User press ESC button
            theme=connection_setting_theme,
            position=[40, 30],
        )

        self.join_game_menu = pygame_menu.Menu(
            'Choosing Games', WINDOW_SIZE[0], WINDOW_SIZE[1],
            center_content=False,
            # onclose=pygame_menu.events.EXIT,  # User press ESC button
            theme=no_title_theme_join_game,
            position=[40, 20],
        )

        self.join_game_menu.set_onbeforeopen(self.cb_join_game_menu_openned)

        self.check_join_menu = pygame_menu.Menu(
            'Game Room Selection', WINDOW_SIZE[0], WINDOW_SIZE[1],
            center_content=True,
            # onclose=pygame_menu.events.EXIT,  # User press ESC button
            theme=no_title_theme_waiting,
            position=[40, 20],
        )

        self.check_join_menu.set_onbeforeopen(self.cb_check_join_menu_openned)

        self.sub_menu_selection0 = pygame_menu.Menu(
            'Choosing Games', WINDOW_SIZE[0], WINDOW_SIZE[1],
            center_content=False,
            onclose=pygame_menu.events.EXIT,  # User press ESC button
            theme=sub_menu_selection0_theme,
            position=[40, 20])

        self.sub_menu_selection0.set_onbeforeopen(self.cb_selection0_menu_opened)

        self.sub_menu_player0_wait = pygame_menu.Menu(
            'Waiting for player', WINDOW_SIZE[0], WINDOW_SIZE[1],
            center_content=False,
            onclose=pygame_menu.events.EXIT,  # User press ESC button
            theme=no_title_theme_waiting,
            position=[40, 20])

        self.sub_menu_player0_wait.set_onbeforeopen(self.cb_player0_wait_menu_opened)

        wait_lbl = self.sub_menu_player0_wait.add.label("Wait for the 2nd player to join...")
        # wait_lbl.set_float(True, False, True)
        # wait_lbl.translate(100, 300)

        self.sub_menu_player1_wait = pygame_menu.Menu(
            'Waiting for player', WINDOW_SIZE[0], WINDOW_SIZE[1],
            center_content=False,
            onclose=pygame_menu.events.EXIT,  # User press ESC button
            theme=no_title_theme_waiting,
            position=[40, 20])

        self.sub_menu_player1_wait.set_onbeforeopen(self.cb_player1_wait_menu_opened)

        wait_lbl = self.sub_menu_player1_wait.add.label("Wait for the 1st player to set the game...")
        wait_lbl.set_float(True, False, True)
        wait_lbl.translate(100, 300)

        # main_menu
        # lbl0 = self.main_menu.add.label("Long long ago.... blah blah blah, click the button to play")
        # lbl0.set_float(True, False, True)
        # lbl0.translate(200, 200)

        lbl1 = self.main_menu.add.label("Disclaimer: you choose to use this program at your own risk", font_size=20)
        lbl1.set_float(True, False, True)
        lbl1.translate(200, 730)

        # self.img_idle_boy = self.main_menu.add.surface(self.lcls["boy_idle_50per"][0], surface_id="boy_idle_50per")
        # self.img_idle_boy.set_float(True, False, True)
        # self.img_idle_boy.translate(65, 100)
        # self.img_idle_boy.set_attribute("idx", 0)
        # self.img_idle_boy.add_draw_callback(self.cb_img_animate)
        #
        # self.img_idle_girl = self.main_menu.add.surface(self.lcls["girl_idle_50per"][0], surface_id="girl_idle_50per")
        # self.img_idle_girl.set_float(True, False, True)
        # self.img_idle_girl.translate(50, 350)
        # self.img_idle_girl.set_attribute("idx", 0)
        # self.img_idle_girl.add_draw_callback(self.cb_img_animate)

        # self.img_idle_girl = self.main_menu.add.surface(self.img_lst_50per[1][0])
        # self.img_idle_girl.set_float(True, False, True)
        # self.img_idle_girl.translate(50, 350)

        ok_btn = self.main_menu.add.button(" ", self.connection_menu, background_color=btn_img_play)
        ok_btn._selected = False
        ok_btn.resize(120, 28)
        ok_btn.set_float(True, False, True)
        ok_btn.translate(450, 280)

        credits_btn = self.main_menu.add.button(" ", self.credits_menu, background_color=btn_img_credits)
        credits_btn.resize(168, 28)
        credits_btn.set_float(True, False, True)
        credits_btn.translate(430, 380)

        # self.main_menu.add.label("font test", "font test")

        credit_frame = self.credits_menu.add.frame_h(800, 800)
        credit_frame.set_float(True, False, True)
        credit_frame.translate(250, 200)
        # credit_frame.set_background_color((0, 0, 0, 100))
        credit_frame.make_scrollarea(510, 380,
                                     scrollarea_color=None,
                                     scrollbar_color=(235, 235, 235, 0),
                                     scrollbar_cursor=None,
                                     scrollbar_slider_color=(200, 200, 200, 0),
                                     scrollbar_slider_hover_color=(180, 180, 180, 0),
                                     scrollbar_slider_pad=0,
                                     scrollbar_thick=20,
                                     scrollbars=('position-south', 'position-east'),
                                     scrollbar_shadow=False,
                                     scrollbar_shadow_color=(0, 0, 0, 0),
                                     scrollbar_shadow_offset=2,
                                     scrollbar_shadow_position='position-southeast')

        for i in range(len(self.credits)):
            lbl = self.credits_menu.add.label(f"{self.credits[i]}", f"{i}")
            lbl_width = credits_theme_font.size(self.credits[i])
            credit_frame.pack(lbl)
            lbl.set_float(True, False, True)
            # print((510-lbl_width[0])/2)
            # lbl.translate(self.credits_x + (510-lbl_width[0]/2), self.credits_y0 + (i) * self.credits_pitch)
            lbl.translate(self.credits_x + (510-(lbl_width[0]))/2, i * self.credits_pitch)
            lbl.add_draw_callback(self.cb_animate_credits)
            # lbl.set_frame(credit_frame)

        self.credits_menu.add.button("Back", pygame_menu.events.BACK)

        # connection menu

        # self.connection_menu.add.vertical_margin(100)

        server_ip = self.connection_menu.add.text_input(
            'Server ip address: ',
            default='127.0.0.1',  # '47.94.100.39'
            onreturn=None,
            textinput_id='server_ip')

        server_port = self.connection_menu.add.text_input(
            'Server port#: ',
            default='8887',
            onreturn=None,
            textinput_id='server_port')

        player_name = self.connection_menu.add.text_input(
            'Your name: ',
            default="Dad",
            onreturn=None,
            textinput_id='new_game',
            maxchar=49
        )

        b_connect = self.connection_menu.add.button("Connection status: <click to connect>",
                                                    self.cb_conn_conn,
                                                    server_ip,
                                                    server_port,
                                                    player_name)
        b_connect.add_self_to_kwargs()

        b_create = self.connection_menu.add.button("Create a new game", self.sub_menu_selection0)
        # b_create.add_self_to_kwargs()

        self.connection_menu.add.button("Choose an existing game to join", self.join_game_menu)

        self.connection_menu.add.button('Quit', pygame_menu.events.EXIT)
        self.connection_menu.add.vertical_margin(50)
        # self.connection_menu.add.label("Disclaimer: you agree to use this program on your own risks.",
        #                                font_color="red",
        #                                font_size=20,
        #                                align=ALIGN_CENTER)
        self.connection_menu.set_sound(all_sound, recursive=True)  # Apply on menu and all sub-menus

        # main_menu end
        # join_game_menu start

        self.join_game_menu.add.vertical_margin(30)

        # refresh_frame = self.join_game_menu.add.frame_h(400, 50, align=ALIGN_LEFT)

        # b_refresh = self.join_game_menu.add.button("refresh",
        #                                            self.cb_refresh,
        #                                            underline=True,
        #                                            cursor=CURSOR_HAND)
        #
        # # b_refresh.add_self_to_kwargs()
        #
        # refresh_frame.pack(self.join_game_menu.add.label("Please"))
        # refresh_frame.pack(b_refresh)
        # refresh_frame.pack(self.join_game_menu.add.label(" the game list!"))

        # self.join_game_menu.add.vertical_margin(15)

        self.selector_game = self.join_game_menu.add.dropselect(
            title='Choose a game to join:',
            items=self.game_rooms,
            default=0,
            onchange=self.cb_dropselector_game_onchange,
            selection_box_bgcolor=(200, 200, 50),
            selection_box_height=10
        )

        self.selector_game.set_float(True, False, True)
        self.selector_game.translate(110, 110)

        self.join_game_menu.add.vertical_margin(15)
        self.b_refresh = self.join_game_menu.add.button("refresh", self.cb_refresh, cursor=CURSOR_HAND,
                                                        background_color=LIGHT_GREEN)
        self.b_refresh.set_float(True, False, True)
        self.b_refresh.translate(750, 110)

        # self.join_game_menu.add.vertical_margin(15)
        #
        # self.join_game_menu.add.button("Back", pygame_menu.events.BACK)
        # self.join_game_menu.add.vertical_margin(15)

        b_quit = self.join_game_menu.add.button("Quit", pygame_menu.events.EXIT,
                                                background_color=LIGHT_GREEN)
        b_quit.set_float(True, False, True)
        b_quit.translate(890, 630)

        # title text can't be empty, otherwise resize doesn't work!
        sub1_btn_lft = self.join_game_menu.add.button(" ", self.cb_role_sel_lft, background_color=btn_img_lft)
        sub1_btn_lft.resize(100, 100)
        sub1_btn_lft.set_attribute("direction", "l")
        sub1_btn_lft.add_self_to_kwargs()
        sub1_btn_lft.set_onmouseleave(self.cb_btn_mouseleave)
        sub1_btn_lft.set_float(True, False, True)
        sub1_btn_lft.translate(150, 300)

        sub1_btn_rgt = self.join_game_menu.add.button(" ", self.cb_role_sel_rgt, background_color=btn_img_rgt)
        sub1_btn_rgt.resize(100, 100)
        sub1_btn_rgt.set_attribute("direction", "r")
        sub1_btn_rgt.add_self_to_kwargs()
        sub1_btn_rgt.set_onmouseleave(self.cb_btn_mouseleave)
        sub1_btn_rgt.set_float(True, False, True)
        sub1_btn_rgt.translate(750, 300)

        for j in range(len(role_def.girl_txt)):
            lbl = self.join_game_menu.add.label(role_def.girl_txt[j][5],
                                                "",
                                                font_size=role_def.girl_txt[j][0],
                                                font_color=role_def.girl_txt[j][1])
            lbl.set_float(True, False, True)
            lbl.translate(role_def.girl_txt[j][2], role_def.girl_txt[j][3])
            lbl.hide()
            self.girl_desc_lbl_lst.append(lbl)

        for j in range(len(role_def.boy_txt)):
            lbl = self.join_game_menu.add.label(role_def.boy_txt[j][5],
                                                "",
                                                font_size=role_def.boy_txt[j][0],
                                                font_color=role_def.boy_txt[j][1])
            lbl.set_float(True, False, True)
            lbl.translate(role_def.boy_txt[j][2], role_def.boy_txt[j][3])
            # lbl.hide()
            self.boy_desc_lbl_lst.append(lbl)

        self.img_join_menu = self.join_game_menu.add.surface(self.current_img_lst[0])
        self.img_join_menu.set_float(True, False, True)
        self.img_join_menu.translate(350, 180)

        self.b_join = self.join_game_menu.add.button("Join", self.check_join_menu, cursor=CURSOR_HAND,
                                                     background_color=LIGHT_GREEN)
        self.b_join.set_float(True, False, True)
        self.b_join.translate(890, 570)

        # ok_btn_sel = self.join_game_menu.add.button(" ", self.sub_menu_player0_wait, background_color=btn_img_ok)
        # ok_btn_sel.resize(100, 100)
        # ok_btn_sel.set_float(True, False, True)
        # ok_btn_sel.translate(890, 570)

        # join_game_menu end
        # check_join_menu start

        self.msg_lbl = self.check_join_menu.add.label("Game room choice accepted, click ok to proceed")
        # self.msg_lbl.set_float(True, False, True)
        # self.msg_lbl.translate(100, 300)

        self.check_join_menu.add.vertical_margin(30)
        self.check_join_back_btn = self.check_join_menu.add.button("Back", pygame_menu.events.BACK)
        self.check_join_ok_btn = self.check_join_menu.add.button("OK", self.sub_menu_player1_wait)
        # self.check_join_ok_btn.set_float(True, False, True)
        # self.check_join_ok_btn.translate(300, 400)

        # check_join_menu end
        # sub_menu_selection0 start

        self.sub_menu_selection0.set_sound(engine, recursive=True)  # Apply on menu and all sub-menus

        lbl_match_type = self.sub_menu_selection0.add.label("Match Types")
        lbl_match_type.set_float(True, False, True)
        lbl_match_type.translate(100, 100)

        selector_match_type = self.sub_menu_selection0.add.dropselect(
            title='',
            items=[("Deathmatch", 0),
                   ("1st23", 1),
                   ("Best of 3", 2)],
            default=0,
            font_size=26,
            selection_box_width=200,
            selection_box_height=100,
            selection_option_padding=(0, 5),
            selection_option_font_size=20,
            onchange=self.cb_selector_match_type_onchange
        )
        selector_match_type.set_float(True, False, True)
        selector_match_type.translate(60, 140)

        lbl_map = self.sub_menu_selection0.add.label("Map Selection")
        lbl_map.set_float(True, False, True)
        lbl_map.translate(680, 100)

        selector_map = self.sub_menu_selection0.add.dropselect(
            title='',
            items=[("Map0", 0),
                   ("Map1", 1),
                   ("Map3", 2)],
            default=0,
            font_size=26,
            selection_box_width=200,
            selection_box_height=100,
            selection_option_padding=(0, 5),
            selection_option_font_size=20,
            onchange=self.cb_selector_map_onchange
        )
        selector_map.set_float(True, False, True)
        selector_map.translate(650, 140)

        # title text can't be empty, otherwise resize doesn't work!
        sub1_btn_lft = self.sub_menu_selection0.add.button(" ", self.cb_role_sel_lft, background_color=btn_img_lft)
        sub1_btn_lft.set_attribute("direction", "l")
        sub1_btn_lft.add_self_to_kwargs()
        sub1_btn_lft.set_onmouseleave(self.cb_btn_mouseleave)
        sub1_btn_lft.resize(100, 100)
        sub1_btn_lft.set_float(True, False, True)
        sub1_btn_lft.translate(150, 300)

        sub1_btn_rgt = self.sub_menu_selection0.add.button(" ", self.cb_role_sel_rgt, background_color=btn_img_rgt)
        sub1_btn_rgt.set_attribute("direction", "r")
        sub1_btn_rgt.add_self_to_kwargs()
        sub1_btn_rgt.set_onmouseleave(self.cb_btn_mouseleave)
        sub1_btn_rgt.resize(100, 100)
        sub1_btn_rgt.set_float(True, False, True)
        sub1_btn_rgt.translate(750, 300)

        for j in range(len(role_def.girl_txt)):
            lbl = self.sub_menu_selection0.add.label(role_def.girl_txt[j][5],
                                                     "",
                                                     font_size=role_def.girl_txt[j][0],
                                                     font_color=role_def.girl_txt[j][1])
            lbl.set_float(True, False, True)
            lbl.translate(role_def.girl_txt[j][2], role_def.girl_txt[j][3])
            lbl.hide()
            self.girl_desc_lbl_lst.append(lbl)

        for j in range(len(role_def.boy_txt)):
            lbl = self.sub_menu_selection0.add.label(role_def.boy_txt[j][5],
                                                     "",
                                                     font_size=role_def.boy_txt[j][0],
                                                     font_color=role_def.boy_txt[j][1])
            lbl.set_float(True, False, True)
            lbl.translate(role_def.boy_txt[j][2], role_def.boy_txt[j][3])
            # lbl.hide()
            self.boy_desc_lbl_lst.append(lbl)

        self.img_selection0 = self.sub_menu_selection0.add.surface(self.current_img_lst[0])
        self.img_selection0.set_float(True, False, True)
        self.img_selection0.translate(350, 180)
        self.img_selection0.add_draw_callback(self.cb_selection0_img_anim)

        ok_btn_sel = self.sub_menu_selection0.add.button(" ", self.sub_menu_player0_wait, background_color=btn_img_ok)
        ok_btn_sel.resize(100, 100)
        ok_btn_sel.set_float(True, False, True)
        ok_btn_sel.translate(890, 570)

        # sub_menu_selection0 end

        img_idx0 = 0
        img_idx1 = 0
        # current_img_idx = 0
        # -------------------------------------------------------------------------
        # Main loop
        # -------------------------------------------------------------------------
        while self.playing:
            self.clock.tick(FPS)
            # print(f"menu = {pygame.time.get_ticks()}")

            events = pygame.event.get()
            self.check_end(events)

            self.main_menu.update(events)

            if self.main_menu.is_enabled():
                # self.screen.blit(background_image, (0, 0))
                if self.main_menu.is_enabled():
                    self.main_menu.draw(self.screen)
            else:
                break

            img_idx0 = self.role_img_animation(self.img_selection0, img_idx0)
            img_idx1 = self.role_img_animation(self.img_join_menu, img_idx1)
            # if self.main_menu.get_current() == self.sub_menu_selection0:
            #     self.splat_font.render_to(self.screen, (100, 100), "render to menu screen")

            # if img_idx + 1 == len(self.current_img_lst) * 2:
            #     img_idx = 0
            # else:
            #     img_idx += 1
            # self.img.set_surface(self.current_img_lst[img_idx // 2])

            # if img_idx // 2 != current_img_idx:
            #     self.img.set_surface(self.current_img_lst[img_idx // 2])

            # Main menu
            # self.main_menu.mainloop(surface, main_background, disable_loop=test, fps_limit=FPS)

            # Flip surface
            pygame.display.flip()

            # At first loop returns
            if test:
                break

m = Menu()
if __name__ == '__main__':
    m.main()
    pygame.quit()
    exit()


# we are using consecutive addition.

# My code logic

nums = [1, 2, 3, 4]
ans = []
sum = 0
for i in nums:
    sum += i
    ans.append(sum)
print(ans)

# Optimized Logic
# Review this logic as it is not working properly

for i in range(1,len(nums)):
    nums[i] += nums[i-1]
print(nums)

Arrays in Python/Easy/Running sum of 1D array.py


'''
Created on Feb 15, 2015

@author: edwingsantos
'''

import pygame
import time
import random

# pygame.locals
displayWidth = 800
displayHeight = 600

white = (255, 255, 255)
black = (0, 0, 0)
red = (200, 0, 0)
green = (0,200,0)
blue = (0,0,255)

brightRed = (255,0,0)
brightGreen = (0,255,0)

blockColor = (53, 115, 255)

pygame.init()

pygame.mixer.init()
pygame.mixer.music.set_volume(1.0)
crashSound = pygame.mixer.Sound("data\boom.wav")

gameDisplay =  pygame.display.set_mode((displayWidth,displayHeight))

iconImage = pygame.image.load("clipart.png").convert_alpha()

pygame.display.set_icon(iconImage)
pygame.display.set_caption('A bity Racey')

raceCar =  pygame.image.load("racecar.png").convert_alpha()

carWidth = 73
tree = pygame.image.load("tree.png").convert_alpha()

clock = pygame.time.Clock()

pause = False

def things_dodge(count):
    font = pygame.font.SysFont(None, 25)
    text = font.render("Dodge:  " + str(count), True, black)
    gameDisplay.blit(text, (0,5))

def things(thingx, thingy, thingw, thingh, color):
    pygame.draw.rect(gameDisplay, color, [thingx, thingy, thingw, thingh] )

def messageDisplay(text):
    largeText = pygame.font.Font('freesansbold.ttf', 105)
    textSurf, textRect = textObjects(text, largeText)
    textRect.center = ((displayWidth / 2 ),(displayHeight / 2))
    gameDisplay.blit(textSurf, textRect)
    pygame.display.update()
    time.sleep(2)
    gameLoop()

def textObjects(text, font):
    textSurface = font.render(text, True, blue)
    return textSurface, textSurface.get_rect()

def crash():
    crashSound.play()

    largeText = pygame.font.SysFont("comicsansms",115)
    TextSurf, TextRect = textObjects("You Crashed", largeText)
    TextRect.center = ((displayWidth/2),(displayHeight/2))
    gameDisplay.blit(TextSurf, TextRect)

    while True:
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        #gameDisplay.fill(white)

        button("Play Again",150,450,100,50, green, brightGreen, gameLoop)
        button("Quit",550,450,100,50, red, brightRed, quitGame)

        pygame.display.update()
        clock.tick(15)

def car(x, y):
    gameDisplay.blit(raceCar,(x,y))

def tree(x, y):
    gameDisplay.blit(tree,(x,y))

x1 = 100
y1 = 100

def button(msg,x,y,w,h,ic,ac,action=None):
    mouse = pygame.mouse.get_pos()
    click = pygame.mouse.get_pressed()
    #print(click)
    if x+w > mouse[0] > x and y+h > mouse[1] > y:
        pygame.draw.rect(gameDisplay, ac,(x,y,w,h))

        if click[0] == 1 and action != None:
            action()
    else:
        pygame.draw.rect(gameDisplay, ic,(x,y,w,h))

    smallText = pygame.font.SysFont("comicsansms",20)
    textSurf, textRect = textObjects(msg, smallText)
    textRect.center = ( (x+(w/2)), (y+(h/2)) )
    gameDisplay.blit(textSurf, textRect)

def gameIntro():

    global pause

    intro = True

    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        #print(event)
        gameDisplay.fill(white)
        largeText = pygame.font.Font('freesansbold.ttf', 100)

        textSurf, textRect = textObjects('A bit Racey', largeText)
        textRect.center = ((displayWidth / 2 ),(displayHeight / 2))
        gameDisplay.blit(textSurf, textRect)

        button("GO!",150,450,100,50,green,brightGreen,gameLoop)
        button("Quit",550,450,100,50,red,brightRed,quitGame)

        pygame.display.update()
        clock.tick(15)

def quitGame():
    pygame.quit()
    quit()

def paused():

    largeText = pygame.font.SysFont("comicsansms",115)
    TextSurf, TextRect = textObjects("Paused", largeText)
    TextRect.center = ((displayWidth/2),(displayHeight/2))
    gameDisplay.blit(TextSurf, TextRect)

    while pause:
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        #gameDisplay.fill(white)

        button("Continue",150,450,100,50, green, brightGreen, unpause)
        button("Quit",550,450,100,50, red, brightRed, quitGame)

        pygame.display.update()
        clock.tick(15)

def unpause():
    global pause
    pause = False

def gameLoop():
    global pause

    x = (displayWidth * 0.45)
    y = (displayHeight * 0.8)

    x_change = 0

    thingStartX = random.randrange(0, displayWidth)
    thingStartY = -600
    thingSpeed = 9
    thingWidth = 100
    thingHight = 100

    dodge = 0

    gameExit = False

    while not gameExit:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    x_change = -8
                if event.key == pygame.K_RIGHT:
                    x_change = 8
                if event.key == pygame.K_p:
                    pause = True
                    paused()

            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    x_change = 0

        x += x_change

        gameDisplay.fill(white)

        things(thingStartX, thingStartY, thingWidth, thingHight, blockColor)
        thingStartY += thingSpeed

        car(x, y)

        things_dodge(dodge)

        #
        #Boundaries or walls
        #
        if x > displayWidth - carWidth or x < 0:
            crash()

        #
        #the black coming down the screen
        #

        if thingStartY > displayHeight:
            thingStartY = 0 - thingHight
            thingStartX = random.randrange(0, displayWidth)
            dodge += 1
            thingSpeed += 1
            thingWidth += (dodge * 0.5)

        #
        #Mainlogic
        #
        if y < thingStartY + thingHight :
            #print ('y cross over')

            if x > thingStartX and x < thingStartX + thingWidth or x + carWidth > thingStartX and x + carWidth < thingStartX+ thingWidth :
                #print ()
                crash()

        pygame.display.update()
        clock.tick(50)

gameIntro()
gameLoop()

if __name__ == '__main__':
    pass


from transformers import AutoModelForCausalLM, AutoTokenizer
from transformers.generation import GenerationConfig
from transformers import AutoConfig
import torch
import argparse

def load(tokenizer_path, checkpoint_path, use_cpu=False):
    print('Loading tokenizer ...')
    tokenizer = AutoTokenizer.from_pretrained(
        tokenizer_path, use_fast=False, trust_remote_code=True, padding_side='left')
    tokenizer.add_tokens("[USER]")
    tokenizer.add_tokens("[BOT]")
    tokenizer.add_tokens("[SEP]")

    print('Loading model ...')
    config = AutoConfig.from_pretrained(checkpoint_path, trust_remote_code=True)
    if use_cpu:
        device_map = "cpu"
    else:
        device_map = "balanced_low_0"

    model = AutoModelForCausalLM.from_pretrained(
        checkpoint_path, config=config, device_map=device_map, torch_dtype=torch.bfloat16, trust_remote_code=True)
    model.generation_config = GenerationConfig.from_pretrained(
        checkpoint_path, trust_remote_code=True)

    model.generation_config.do_sample = True
    model.eval()

    if tokenizer.pad_token_id is None:
        if tokenizer.eos_token_id is not None:
            tokenizer.pad_token_id = tokenizer.eos_token_id
        else:
            tokenizer.pad_token_id = 0

    return model, tokenizer

def special_encode(prompt, tokenizer):
       raw_str = "[USER]%s[SEP][BOT]" % prompt.strip().replace("\r", "")
       bos_id = tokenizer.bos_token_id
       eos_id = tokenizer.eos_token_id
       sep_id = tokenizer.encode("[SEP]")[-1]
       res_id = [eos_id, bos_id]
       arr = raw_str.split("[SEP]")
       for elem_idx in range(len(arr)):
              elem = arr[elem_idx]
              elem_id = tokenizer.encode(elem)[1:]
              res_id += elem_id
              if elem_idx < len(arr) - 1:
                     res_id.append(sep_id)
       return res_id

def extract_res(response):
    if "[BOT]" in response:
        response = response.split("[BOT]")[1]
    if "<s>" in response:
        response = response.split("<s>")[-1]
    if "</s>" in response:
        response = response.split("</s>")[0]
    if "[SEP]" in response:
        response = response.split("[SEP]")[0]
    return response[1:]

if __name__ == '__main__':
    parser = argparse.ArgumentParser("Skywork-cli-demo")
    parser.add_argument("-m", "--model_path", type=str, default="skywork-13b-chat")
    parser.add_argument("-n", "--max_new_tokens", type=int, default=1000)
    parser.add_argument("-t", "--temperature", type=float, default=0.95)
    parser.add_argument("-p", "--top_p", type=float, default=0.8)
    parser.add_argument("-k", "--top_k", type=int, default=5)
    parser.add_argument("--cpu", action='store_true', help="inference with cpu")

    args = parser.parse_args()

    model, tokenizer = load(args.model_path, args.model_path, args.cpu)

    while True:

        doc = input("输入：")
        input_tokens = special_encode(doc, tokenizer)
        input_tokens = torch.tensor(input_tokens).to(model.device).reshape(1, -1)
        response = model.generate(input_tokens,
                                 max_new_tokens=args.max_new_tokens,
                                 pad_token_id=tokenizer.pad_token_id,
                                 do_sample=True,
                                 top_p=args.top_p,
                                 top_k=args.top_k,
                                 temperature=args.temperature,
                                 num_return_sequences=1,
                                 repetition_penalty=1.1,
                                 bos_token_id=1,
                                 eos_token_id=2)
        response = tokenizer.decode(response.cpu()[0], skip_special_tokens=True)
        response = extract_res(response)
        print("模型输出：")
        print(response)