import cocotb
from cocotb_bus.drivers import BusDriver
from cocotb.triggers import ClockCycles, FallingEdge, First, RisingEdge
from cocotb.result import TestFailure

import copy

class Axi4StreamMaster(BusDriver):
    """
    AXI4-Stream Master
    """

    _signals = ["TVALID"]

    _optional_signals = [
        "TREADY", "TDATA", "TLAST", "TSTRB", "TKEEP", "TID", "TDEST", "TUSER"
    ]

    def __init__(self, entity, name, clock):
        """
            Initialization of AxiStreamMaster

            Args:
                entity: handle to the simulator entity
                name: Name of the bus
                clock: handle to the clk associated with this bus
        """

        BusDriver.__init__(self, entity, name, clock)
        self.clock = clock

        # Drive some sensible defaults (setimmediatevalue to avoid x asserts)
        for signal in self._signals + self._optional_signals:
            if signal != "TREADY":
                try:
                    default_value = \
                        2 ** getattr(self.bus, signal).value.n_bits - 1 \
                        if signal in ("TSTRB", "TKEEP") else 0
                    getattr(self.bus, signal).setimmediatevalue(default_value)
                except AttributeError:
                    pass

    @cocotb.coroutine
    async def write(self, data, sync=True, tlast_on_last=True):
        """
        Write one or more values on the bus.

        Args:
            data (int/dict or iterable of int/dict): the data values to write.
                Each dict represents an AXI4-Stream transfer, where the dict's
                keys are the signal names and the values are the values to
                write. Missing signals are kept constant.
                Each int represents the TDATA signal in the AXI4-Stream
                transfer (so, they are equivalent to {"TDATA": int_value}).
            sync (bool, optional): wait for rising edge on clock initially.
                Defaults to True.
            tlast_on_last(bool, optional): assert TLAST on the last word
                written on the bus.
                Defaults to True.
        """

        try:
            if isinstance(data, dict):
                # Treat dict as not iterable to avoid wrong results when using
                # enumerate method to retrieve data signals.
                raise TypeError
            iter(data)
        except TypeError:
            data = (data,)    # If data is not iterable, make it

        data = copy.copy(data)

        if sync:
            await RisingEdge(self.clock)

        self.bus.TVALID.value = 1

        for index, word in enumerate(data):
            # If word is not a dict, make it (using word as "TDATA")
            if not isinstance(word, dict):
                word = {"TDATA": word}

            for signal, value in word.items():
                err_msg = \
                    f"During transfer {index}, signal {signal} has been " \
                    "passed, but it is "
                if signal == 'TREADY':
                    raise TestFailure(err_msg + "an input for the driver")
                elif signal == 'TLAST' and tlast_on_last:
                    raise TestFailure(err_msg + "already controlled by the "
                                                "driver (tlast_on_last=True)")
                elif signal not in Axi4StreamMaster._optional_signals:
                    raise TestFailure(err_msg + "not a valid "
                                                "AXI4-Stream signal")

                try:
                    getattr(self.bus, signal).value = value
                except AttributeError:
                    raise TestFailure(err_msg + "not present on the bus")

            if hasattr(self.bus, "TLAST") and tlast_on_last and \
               index == len(data) - 1:
                self.bus.TLAST.value = 1

            await RisingEdge(self.clock)
            while hasattr(self.bus, "TREADY") and not self.bus.TREADY.value:
                await RisingEdge(self.clock)

        if hasattr(self.bus, "TLAST") and tlast_on_last:
            self.bus.TLAST.value = 0

        self.bus.TVALID.value = 0

    @property
    def n_bits(self):
        return self.bus.TDATA.value.n_bits

class Axi4StreamSlave(BusDriver):
    """
    AXI4-Stream Slave

    Generates configurable TREADY patterns.
    """

    _signals = ["TVALID"]

    # Only TREADY is used in this design, all other signals are unused
    _optional_signals = [
        "TREADY", "TDATA", "TLAST", "TSTRB", "TKEEP", "TID", "TDEST", "TUSER"
    ]

    def __init__(self, entity, name, clock, tready_delay=-1,
                 consecutive_transfers=0):
        """
            Initialization of AxiStreamSlave

            Args:
                entity: handle to the simulator entity
                name: name of the bus
                clock: handle to the clk associated with this bus
                tready_delay (int or callable, optional): number of delay clock
                    cycles between a high TVALID and the assertion of TREADY.
                    Can also be a function, which is called at the TVALID
                    rising edge and should return the number of delay cycles to
                    assert TREADY (non negative number).
                    Defaults to -1 , which sets TREADY always to 1, regardless
                    of the value of TVALID.
                consecutive_transfers (int or callable, optional): the maximum
                    number of uninterrupted transfers (high TVALID and TREADY
                    on consecutive clock cycles) after which TREADY will be
                    de-asserted and the tready_delay will be restarted. Ignored
                    when tready_delay = -1.
                    Can also be a function, which is called at the beginning of
                    each transfer and should return the maximum allowed number
                    of consecutive transfers (non negative number).
                    Default to 0, which allows an unlimited number of
                    consecutive transfers.
        """

        BusDriver.__init__(self, entity, name, clock)

        # If TREADY is not present, this Driver does nothing
        if hasattr(self.bus, "TREADY"):
            if not callable(tready_delay) and tready_delay == -1:
                # If TREADY has to be always high, just set it to 1
                self.bus.TREADY.setimmediatevalue(1)
            else:
                # If not, set it to zero and fork _receive_data
                self.bus.TREADY.setimmediatevalue(0)
                self.clock = clock
                self.tready_delay = tready_delay
                self.consecutive_transfers = consecutive_transfers

                cocotb.start_soon(self._receive_data())

    @cocotb.coroutine
    async def _receive_data(self):

        while True:
            # Wait for a high TVALID, if not already high
            if not self.bus.TVALID.value:
                await RisingEdge(self.bus.TVALID)

            # Wait either for the required number of clock cycles or for a low
            # TVALID. By AXI4-Stream standard, the master should not de-assert
            # TVALID until at least one transfer has been performed but, if it
            # does it anyways, just re-start the wait.
            if callable(self.tready_delay):
                tready_high_delay = ClockCycles(self.clock,
                                                self.tready_delay(self.bus))
            else:
                tready_high_delay = ClockCycles(self.clock, self.tready_delay)

            trigger = await First(tready_high_delay,
                                  FallingEdge(self.bus.TVALID))

            if trigger is tready_high_delay:
                self.bus.TREADY.value = 1

                if callable(self.consecutive_transfers):
                    num_cycles = self.consecutive_transfers(self.bus)
                else:
                    num_cycles = self.consecutive_transfers

                if num_cycles != 0 and tready_high_delay != -1:
                    await First(ClockCycles(self.clock, num_cycles),
                                FallingEdge(self.bus.TVALID))
                else:
                    await FallingEdge(self.bus.TVALID)

                self.bus.TREADY.value = 0
                await RisingEdge(self.clock)


# coding:utf-8

"""
Author: Michael Shu
Created: 2020-06-30
Note:

Simple OCR Letters

Write a web service which can take an uploaded image(jpg, png) and find any letters in it.

The result will be returned to user as JSON :

{"content": [ 'Letter1', 'Letter2'...]}
This result will also be saved to database for future use.

Requirements:
Design your own data model and API
Use any Python/Golang frameworks or libraries as needed
Should include tests and documentations
"""

import os
import json
import sqlite3
from flask import Flask, jsonify, request
from model.ocr import ocr_do
from config import config
from db.affair_db import upload_insert_sql

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

def response_data(success=True, message="success", body=None):
    response_dict = {"success": success,
                    "message": message,
                    "body": body}
    return jsonify(response_dict)

@app.route('/simple-ocr/v1/image-letters', methods=['POST'])
def ocr_analysis():
    if request.method == 'POST':
        f = request.files['image_file']
        res, content = ocr_do.get_content_from_image(f)
        if not res:
            return (response_data(False, "ocr analysis image err, reason: {0}.".format(content)), "500")
        if content is None or content == "":
            return (response_data(False, "content is Null."), "500")

        res, letters_dict = ocr_do.analysis_content_to_json(content)
        if not res:
            return (response_data(False, "analysis content err, reason: {0}.".format(letters_dict)), "500")

        res, reason = upload_insert_sql(letters_dict.keys()[0], json.dumps(letters_dict))
        if not res:
            return (response_data(False, "save to database err, reason: {0}.".format(reason)), "500")

        return response_data(body=letters_dict)
    else:
        return (response_data(False, "server only support POST."), "405")

if __name__ == '__main__':
    app.debug = config.is_debug
    app.run()


#
# Complete the 'weightedMean' function below.
#
# The function accepts following parameters:
#  1. INTEGER_ARRAY X
#  2. INTEGER_ARRAY W
#

def weightedMean(X, W):

    weighted_arr = [elem*weight for elem,weight in zip(X,W)]

    return sum(weighted_arr)/sum(W)

if __name__ == '__main__':

    n = int(input().strip())

    vals = list(map(int, input().rstrip().split()))

    weights = list(map(int, input().rstrip().split()))

    # round result for exercise to 1 digit
    print(round(weightedMean(vals, weights),1))


import re
import discord
import os
from discord.ext import commands

async def log(client, value):
    l = client.get_channel(int(os.environ["log_channel"]))
    await l.send(str(value))

async def checkUniversityUsername(m):
    if len(m) != 8:
        return False
    regex = r'^([A-C|a-c])\d{7}$'
    if re.match(regex, m):
        return True
    else:
        return False

async def userInputDM(client, ctx, str):
    while True:
        msg = await client.wait_for("message")
        if ctx.author == msg.author and isinstance(msg.channel, discord.channel.DMChannel):
            if msg.content.lower() == str.lower() or re.match(str, msg.content.lower()):
                break
            else:
                await ctx.author.send("Invalid input, please try again")
    return msg


import pandas as pd
from dateutil import parser
from fastapi import APIRouter
from sklearn import preprocessing

from orm.tables import Measurement

router = APIRouter()
from datetime import date
from typing import List

from dateutil import parser
from dateutil.parser._parser import ParserError
from fastapi import APIRouter, HTTPException
from fastapi.params import Path
from pydantic import BaseModel

from orm.tables import Apartment, Measurement

router = APIRouter()

@router.get("/kpis/weekly-change/{apartment_id}", response_model=float, tags=["kpi"])
async def get_user_weekly_trend(
    apartment_id: int = Path(..., title="The ID of the apartment to get data for", ge=0)
):
    try:
        two_week = Measurement.raw(
            """
            select
                date(timestamp),
                sum(water_consumption)
            from measurement
            where
                apartment = {}
            group by date(timestamp) limit(14)
            """,
            apartment_id,
        ).run_sync()
        first_sum = 0
        second_sum = 0
        for i in range(0, 7):
            first_sum += two_week[i]["sum"]
        for i in range(7, 14):
            second_sum += two_week[i]["sum"]
        return round((1 - first_sum / second_sum) * 100, 1)
    except Exception as e:
        print(e)

@router.get("/kpis/hygiene-scores/{group_id}/{date}", tags=["kpi"])
async def hygiene_scores(group_id: int, date: str):
    measurements = Measurement.raw(
        """
        select
            flow_time,
            apartment
        from measurement
        where
            appliance = 'Optima_faucet' and date(timestamp) = {}
            and apartment in (
                select apartment from apartment_groups where group_id = {}
            )
        """,
        parser.parse(date),
        group_id,
    ).run_sync()
    df = pd.DataFrame(measurements)
    df["flow_dist"] = abs(df["flow_time"] - 20)
    flow_df = df[["apartment", "flow_dist"]]
    grouped_df = flow_df.groupby(["apartment"]).mean()
    x_scaled = preprocessing.minmax_scale(X=grouped_df["flow_dist"]) * 100
    grouped_df["hygiene_score"] = x_scaled.round(decimals=0)
    grouped_df.drop(columns=["flow_dist"], inplace=True)
    apm_dict = grouped_df.to_dict(orient="index")
    return apm_dict

class DailyConsumption_Response(BaseModel):
    consumption: float
    apartment_id: int
    date: date

@router.get(
    "/kpis/consumption-daily/{apartment_id}/{date}",
    response_model=DailyConsumption_Response,
    tags=["consumption"],
)
async def get_consumption(
    apartment_id: int = Path(..., title="The ID of the apartment to get data for", ge=0),
    date: str = Path(..., title="The date to get data for"),
):
    try:
        data = Measurement.raw(
            """
            select
                sum(water_consumption) as consumption,
                a.id as apartment_id,
                date(m.timestamp)
            from measurement m
            join apartment a
                on m.apartment = a.id
            where
                a.id = {} and
                date(m.timestamp) = {}
            group by a.id, date(m.timestamp)
            limit 1
        """,
            apartment_id,
            parser.parse(date),
        ).run_sync()
        return data[0] if len(data) != 0 else {}
    except ParserError:
        return HTTPException(422, detail="Invalid string format, please use YYYY-MM-DD")
    except Exception as e:
        print(e)
        return HTTPException(500)

class ConsumptionLastTwoWeeks_Response(BaseModel):
    week_start: date
    weekday: str
    apartment_id: int
    consumption: float

@router.get(
    "/kpis/consumption-weekly/{apartment_id}/{num_weeks}",
    response_model=List[ConsumptionLastTwoWeeks_Response],
    tags=["consumption"],
)
async def get_consumption_last_two_week(
    apartment_id: int = Path(..., title="The ID of the apartment to get data for", ge=0),
    num_weeks: int = Path(..., title="The number of weeks to get data for"),
):
    try:
        data = Measurement.raw(
            """
            select
                date(date_trunc('week', m.timestamp)) as week_start,
                trim(to_char(date(m.timestamp), 'Day')) as weekday,
                date(m.timestamp),
                a.id as apartment_id,
                sum(water_consumption) as consumption
            from measurement m
            join apartment a
                on m.apartment = a.id
            where a.id = {}
            group by
                a.id, date(m.timestamp),
                week_start
            order by
                a.id, date(m.timestamp) desc,
                week_start desc
            limit {};
        """,
            int(apartment_id),
            int(num_weeks) * 7,
        ).run_sync()
        return data
    except ParserError:
        return HTTPException(422, detail="Invalid string format, please use YYYY-MM-DD")
    except Exception as e:
        print(e)
        return HTTPException(500)

@router.get("/kpis/sustainability-scores/{group_id}/{date}", tags=["kpi"])
async def sustainability_scores(group_id: int, date: str):
    measurements = Measurement.raw(
        """
        select sum(x.sus_score) as sustainability_score, x.apartment
        from
            (select
                water_consumption * temp as sus_score,
                apartment
            from measurement
            where
                date(timestamp) = {} and
                apartment in (
                    select apartment
                    from apartment_groups where group_id = {}
                )
            ) as x
        group by x.apartment""",
        parser.parse(date),
        group_id,
    ).run_sync()
    df = pd.DataFrame(measurements)
    apartment_data = Apartment.raw("SELECT id as apartment, people FROM apartment").run_sync()
    apartment_df = pd.DataFrame(apartment_data)
    df = df.merge(apartment_df, on="apartment")
    df["sustainability_score"] = df["sustainability_score"] / df["people"]
    x_scaled = preprocessing.minmax_scale(X=df["sustainability_score"]) * 100
    df["sustainability_score"] = x_scaled.round(decimals=0)
    df.set_index("apartment", inplace=True)
    df.drop(columns=["people"], inplace=True)
    sus_score_dict = df.to_dict("index")
    return sus_score_dict


import scrapy
import lxml.etree as le
import pandas as pd
import numpy as np
import re
import json

url_level1 = 'https://www.carlist.my/used-cars-for-sale/bmw/malaysia'
url_level2 = 'https://www.carlist.my/used-cars-for-sale/{brands}/malaysia?page_number={number}&page_size=25'

class CarlistSpider(scrapy.Spider):
    name = 'carlist'
    #allowed_domains = ['carlist.my']

    def start_requests(self):
        yield scrapy.Request(
            url = url_level1,
            callback=self.parse_start
        )

    def parse_start(self, response):

        text = response.body.decode('gbk', 'ignore')
        text = text.replace("\n", "").replace("'", "")
        texts = le.HTML(text).xpath('//ul[@class="smenu__select smenu__select--brand"]//text()')

        conv = []
        for element in texts:
            conv.append(element.strip())

        while ("" in conv):
            conv.remove("")

        brands = conv[1::2]
        numbers = conv[0::2]
        dictionary = dict(zip(brands, numbers))
        first_pair = list(dictionary.items())

        for element in first_pair:
            brands = element[0].lower().replace(" ", "-")
            number = int(np.ceil(int(element[1].replace(",", "")) / 25))
            for page in range(1, number+1):
                yield scrapy.Request(
                    url=url_level2.format(brands=brands, number=page),
                    callback=self.parse1,
                )

    def parse1(self, response):

        text = response.body.decode('gbk', 'ignore')
        text = text.replace("\n", "").replace("'", "")
        json_str = re.findall('json">(.*?)</script>', text)[0]
        datas = json.loads(json_str)
        datas1 = datas[1]['itemListElement']
        df = pd.json_normalize(datas1)
        yield df.to_csv('out.csv',mode='a', index=True, header=False)


# -*- coding: utf-8 -*-

from ppodd.core import *

class rio_psap(cal_base):
    """
PSAP processing module

:INPUTS:
  | AERACK_psap_flow
  | AERACK_psap_lin
  | AERACK_psap_log
  | AERACK_psap_transmission

:OUTPUTS:
  | PSAP_LIN - Uncorrected absorption coefficient at 565nm, linear, from PSAP
  | PSAP_LOG - Uncorrected absorption coefficient at 565nm, log, from PSAP
  | PSAP_FLO - PSAP Flow
  | PSAP_TRA - SAP Transmittance

:FLAGGING:
  | using flow and transmission thresholds
  | flag[(psap_transmission<0.5) | (psap_transmission>1.05)]=1
  | ix=np.where(psap_flow < 1.0)[0]
  | #add two second buffer to the index
  | ix=np.unique(np.array([list(ix+i) for i in range(-2,3)]))
  | ix=ix[(ix >= 0) & (ix < n-1)]
  | flag[ix]=2
  | flag[((psap_transmission<0.5) | (psap_transmission>1.05)) & (psap_flow<1.0)]=3

"""

    def __init__(self,dataset):
        self.input_names=['AERACK_psap_flow',
                          'AERACK_psap_lin',
                          'AERACK_psap_log',
                          'AERACK_psap_transmission']

        self.outputs=[parameter('PSAP_LIN',
                                units='m-1',
                                frequency=1,
                                number=648,
                                long_name='Uncorrected absorption coefficient at 565nm, linear, from PSAP'),
                      parameter('PSAP_LOG',
                                units='1',
                                frequency=1,
                                number=649,
                                long_name='Uncorrected absorption coefficient at 565nm, log, from PSAP'),
                      parameter('PSAP_FLO',
                                units='standard l min-1',
                                frequency=1,
                                long_name='PSAP Flow'),
                      parameter('PSAP_TRA',
                                units='percent',
                                frequency=1,
                                long_name='PSAP Transmittance')]

        self.version=1.00
        cal_base.__init__(self,dataset)

    def process(self):
        match=self.dataset.matchtimes(self.input_names)
        psap_flow=self.dataset['AERACK_psap_flow'].ismatch(match)
        psap_flow*=0.5
        psap_lin=self.dataset['AERACK_psap_lin'].ismatch(match)
        psap_lin=psap_lin*0.5E-5
        psap_log=self.dataset['AERACK_psap_log'].ismatch(match)
        psap_log=10.0**((psap_log/2.0)-7.0)
        psap_transmission=self.dataset['AERACK_psap_transmission'].ismatch(match)
        psap_transmission*=0.125

        n=psap_flow.size
        # create default flag array set to 0
        flag=np.array([0]*n, dtype=np.int8)
        # Flagging using flow and transmission thresholds
        flag[(psap_transmission<0.5) | (psap_transmission>1.05)]=1
        ix=np.where(psap_flow < 1.0)[0]
        # add two second buffer to the index
        ix=np.unique(np.array([list(ix+i) for i in range(-2,3)]))
        ix=ix[(ix >= 0) & (ix < n-1)]
        flag[ix]=2
        flag[((psap_transmission<0.5) | (psap_transmission>1.05)) & (psap_flow<1.0)]=3

        self.outputs[0].data=flagged_data(psap_lin, psap_lin.times, flag)
        self.outputs[1].data=flagged_data(psap_log, psap_log.times, flag)
        self.outputs[2].data=flagged_data(psap_flow, psap_flow.times, flag)
        self.outputs[3].data=flagged_data(psap_transmission, psap_transmission.times, flag)
        return


#!/usr/bin/env python3
"""Class definitions for station, platform and train"""

class Train:
    """Contains information about one snapshot of a train's position in
       relation to a platform at a station."""
    def __init__(self, lcid, setNo, tripNo, secondsTo, location, destination,
                 destCode, trackCode, ln, whenCreated):
        self.lcid = lcid
        self.setNo = setNo
        self.tripNo = tripNo
        self.secondsTo = secondsTo
        self.location = location
        self.destination = destination
        self.destCode = destCode
        self.trackCode = trackCode
        self.ln = ln
        self.whenCreated = whenCreated

class Platform:
    """Contains information about a platform."""
    def __init__(self, number, name, trackCode):
        self.number = number
        self.name = name
        self.trackCode = trackCode
        self.trains = []
    def addTrain(self, lcid, setNo, tripNo, secondsTo, location, destination,
                 destCode, trackCode, ln, whenCreated):
        """Create, add and return a train object, in relation to this
           platform."""
        train = Train(lcid, setNo, tripNo, secondsTo, location, destination,
                      destCode, trackCode, ln, whenCreated)
        self.trains.append(train)
        return train
    def getTrainByLcid(self, lcid):
        """Get a train by the leading carriage ID."""
        return [x for x in self.trains if x.lcid == lcid][0]
    def getTrainBySetTripNo(self, setNo, tripNo):
        """Get a train by set and trip numbers."""
        return [x for x in self.trains if x.setNo == setNo
                and x.tripNo == tripNo][0]
    def getTrainBySetNo(self, setNo):
        """Get a train by set number only."""
        return [x for x in self.trains if x.setNo == setNo][0]

class Station:
    """Contains information about a station."""
    def __init__(self, code, name, lineCode, lineName):
        self.code = code
        self.name = name
        self.lineCode = lineCode
        self.lineName = lineName
        self.platforms = []
    def addPlatform(self, number, name, trackCode):
        """Create, add and return a platform object for this station."""
        platform = Platform(number, name, trackCode)
        self.platforms.append(platform)
        return platform
    def getPlatform(self, number):
        """Get a platform by number."""
        return [x for x in self.platforms if x.number == number][0]


from app import db
from random_name import get_name
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.inspection import inspect

class ModelBase(object):
    __exclude__ = []

    def serialize(self):
        attrs = [a for a in inspect(self).attrs.keys() if a not in self.__class__.__exclude__]
        return {c: getattr(self, c) for c in attrs}

    @staticmethod
    def serialize_list(l):
        return [m.serialize() for m in l]

class Group(db.Model, ModelBase):
    __tablename__ = 'group'
    __exclude__ = ['id']
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(), nullable=False, unique=True)

    @staticmethod
    def generate_name():
        for i in range(1, 10):
            name = get_name()
            if not Group.query.filter_by(name=name).first():
                return name

    @staticmethod
    def get_or_create(name):
        group = Group.query.filter_by(name=name).first()
        if not group:
            group = Group(name=name)
            db.session.add(group)
            db.session.commit()

        return group

    def serialize(self):
        d = super(Group, self).serialize()
        d['posts'] = [p.serialize() for p in d['posts']]
        return d

    def add_post(self, url, text):
        post = Post(group=self, url=url, text=text)
        db.session.add(post)
        db.session.commit()

class Post(db.Model, ModelBase):
    __tablename__ = 'post'
    __exclude__ = ['id', 'group']

    id = db.Column(db.Integer, primary_key=True)
    group_id = db.Column(db.Integer, ForeignKey('group.id'))
    group = relationship(Group, backref=backref('posts', uselist=True))
    url = db.Column(db.String())
    text = db.Column(db.String())


from django.db import migrations

def add_fieldlist(ResultTableField, table_id, fieldlist):
    for field in fieldlist:
        defaults = {
            "field_type": field["field_type"],
            "description": field["description"],
            "unit": field["unit"],
            "tag": field["tag"],
            "is_config_by_user": True,
            "creator": "system",
            "last_modify_user": "system",
        }
        ResultTableField.objects.update_or_create(table_id=table_id, field_name=field["field_name"], defaults=defaults)

def add_basereport_metrics(apps, *args, **kwargs):
    # 获取APP models
    ResultTableField = apps.get_model("metadata", "ResultTableField")

    cpu_summary_detail_metrics = [
        {
            "field_name": "nice",
            "field_type": "double",
            "description": "低优先级程序在用户态执行的CPU占比",
            "tag": "metric",
            "unit": "percentunit",
        },
        {
            "field_name": "interrupt",
            "field_type": "double",
            "description": "硬件中断数的CPU占比",
            "tag": "metric",
            "unit": "percentunit",
        },
        {
            "field_name": "softirq",
            "field_type": "double",
            "description": "软件中断数的CPU占比",
            "tag": "metric",
            "unit": "percentunit",
        },
        {
            "field_name": "guest",
            "field_type": "double",
            "description": "内核在虚拟机上运行的CPU占比",
            "tag": "metric",
            "unit": "percentunit",
        },
    ]

    env_metrics = [
        {"field_name": "maxfiles", "field_type": "int", "description": "最大文件描述符", "tag": "metric", "unit": "short"},
        {"field_name": "login_user", "field_type": "int", "description": "登录的用户数", "tag": "metric", "unit": "short"},
        {
            "field_name": "proc_running_current",
            "field_type": "int",
            "description": "正在运行的进程总个数",
            "tag": "metric",
            "unit": "short",
        },
        {
            "field_name": "procs_blocked_current",
            "field_type": "int",
            "description": "处于等待I/O完成的进程个数",
            "tag": "metric",
            "unit": "short",
        },
        {
            "field_name": "procs_processes_total",
            "field_type": "int",
            "description": "系统启动后所创建过的进程数量",
            "tag": "metric",
            "unit": "short",
        },
        {
            "field_name": "procs_ctxt_total",
            "field_type": "int",
            "description": "系统上下文切换次数",
            "tag": "metric",
            "unit": "short",
        },
    ]

    load_metrics = [
        {
            "field_name": "per_cpu_load",
            "field_type": "float",
            "description": "单核CPU的load",
            "tag": "metric",
            "unit": "none",
        },
    ]

    net_metrics = [
        {"field_name": "errors", "field_type": "int", "description": "网卡错误包", "tag": "metric", "unit": "short"},
        {"field_name": "dropped", "field_type": "int", "description": "网卡丢弃包", "tag": "metric", "unit": "short"},
        {"field_name": "overruns", "field_type": "int", "description": "网卡物理层丢弃", "tag": "metric", "unit": "short"},
        {
            "field_name": "carrier",
            "field_type": "int",
            "description": "设备驱动程序检测到的载波丢失数",
            "tag": "metric",
            "unit": "short",
        },
        {"field_name": "collisions", "field_type": "int", "description": "网卡冲突包", "tag": "metric", "unit": "short"},
    ]

    swap_metrics = [
        {"field_name": "swap_in", "field_type": "float", "description": "swap从硬盘到内存", "tag": "metric", "unit": "KBs"},
        {"field_name": "swap_out", "field_type": "float", "description": "swap从内存到硬盘", "tag": "metric", "unit": "KBs"},
    ]

    add_fieldlist(ResultTableField, "system.cpu_summary", cpu_summary_detail_metrics)
    add_fieldlist(ResultTableField, "system.cpu_detail", cpu_summary_detail_metrics)
    add_fieldlist(ResultTableField, "system.env", env_metrics)
    add_fieldlist(ResultTableField, "system.load", load_metrics)
    add_fieldlist(ResultTableField, "system.net", net_metrics)
    add_fieldlist(ResultTableField, "system.swap", swap_metrics)

class Migration(migrations.Migration):

    dependencies = [
        ("metadata", "0067_datasource_consul_prefix"),
    ]

    operations = [migrations.RunPython(add_basereport_metrics)]


import csv
import math
import random

def load_csv(filename):
    dataset = list()
    with open(filename) as csv_file:
        rows = csv.reader(csv_file, delimiter=',')
        for row in rows:
            dataset.append([float(x) for x in row])
    return dataset

def split_dataset(dataset, split_ratio, is_random=False):
    train_size = int(len(dataset) * split_ratio)
    train_set = []
    if is_random:
        copy = list(dataset)
        while len(train_set) < train_size:
            index = random.randrange(len(copy))
            train_set.append(copy.pop(index))
        return [train_set, copy]
    return [dataset[:train_size], dataset[train_size:]]

def separate_by_class(dataset):
    separated = {}
    for i in range(len(dataset)):
        vector = dataset[i]
        if vector[-1] not in separated:
            separated[vector[-1]] = []
        separated[vector[-1]].append(vector)
    # print(separated)
    return separated

def mean(numbers):
    return sum(numbers)/float(len(numbers))

def stdev(numbers):
    avg = mean(numbers)
    variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1)
    return math.sqrt(variance)

def summarize(dataset):
    summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]
    del summaries[-1]
    return summaries

def summarize_by_class(dataset):
    separated = separate_by_class(dataset)
    summaries = {}
    for classValue, instances in separated.items():
        summaries[classValue] = summarize(instances)
    return summaries

def calculate_probability(x, x_mean, x_stdev):
    exponent = math.exp(-(math.pow(x - x_mean, 2) / (2 * math.pow(x_stdev, 2))))
    return (1 / (math.sqrt(2*math.pi) * x_stdev)) * exponent

def calculate_class_probabilities(summaries, input_vector):
    probabilities = {}
    for classValue, classSummaries in summaries.items():
        probabilities[classValue] = 1
        for i in range(len(classSummaries)):
            xmean, xstdev = classSummaries[i]
            x = input_vector[i]
            probabilities[classValue] *= calculate_probability(x, xmean, xstdev)
    return probabilities

def predict(summaries, input_vector):
    probabilities = calculate_class_probabilities(summaries, input_vector)
    best_label, best_prob = None, -1
    for classValue, probability in probabilities.items():
        if best_label is None or probability > best_prob:
            best_prob = probability
            best_label = classValue
    return best_label

def get_predictions(summaries, test_set):
    predictions = []
    for i in range(len(test_set)):
        result = predict(summaries, test_set[i])
        predictions.append(result)
    return predictions

def get_accuracy(test_set, predictions):
    correct = 0
    for x in range(len(test_set)):
        # print('Test Set: {0}'.format(test_set[x]), sep='')
        # print('Prediction: {0}'.format(predictions[x]))
        if test_set[x][-1] == predictions[x]:
            correct += 1
    return (correct / float(len(test_set))) * 100.0

def main():
    filename = 'red-wine-quality.csv'
    split_ratio = 0.67
    dataset = load_csv(filename)
    training_set, test_set = split_dataset(dataset, split_ratio, False)
    print('Split {0} rows into train = {1} and test = {2} rows'.format(len(dataset), len(training_set), len(test_set)))
    # prepare model
    model = summarize_by_class(training_set)
    # test model
    predictions = get_predictions(model, test_set)
    accuracy = get_accuracy(test_set, predictions)
    print('Accuracy: {0}'.format(accuracy))

if __name__ == '__main__':
    main()


import numpy as np
import scipy.optimize as op

def load_data(filename):
    '''
    这里我的读取想法是，将文件按行str->list,然后lists->array
    '''
    data = [ ]
    with open(filename,"r") as f :
        line = f.readline()#读取文本文件中的一行
        while line:
            each_line = line.strip().split(',')#将读取出来的一行字符串以“，”为间隔返回一个列表
            data_line = [ float(x) for x in each_line ]#将数列里的元素转换为浮点型
            data_line[2] = int(data_line[2])
            f.readline()#为了跳过两行中空的一行
            data.append(data_line)
            line = f.readline()
    return data#返回生成的列表

def X_polynomial(X1,X2):#求多项式矩阵
    out = np.ones((X1.shape[0], 1))
    for i in np.arange(1, 6 + 1, 1):
        for j in np.arange(0, i + 1, 1):
            temp = X1 ** (i - j) * X2 ** (j)
            out = np.hstack((out, temp))
    return out

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def cost_function(theta,X,y):
    num_X = X.shape[0]
    theta = theta.reshape(X.shape[1], 1)
    cost = np.sum(np.dot((-y).T, np.log(sigmoid(np.dot(X,theta)))) - np.dot((1 - y).T,\
    np.log(1 - sigmoid(np.dot(X,theta))))) / num_X + 0.5 * 1 * np.dot(theta.T,theta) / num_X
    return cost

def gradient(theta,X,y):
    num_X = X.shape[0]
    theta = theta.reshape(X.shape[1],1)#这里添加reshape一开始我想不明白，本来以为它一开始不就是这个shape吗？为什么还要重新reshape一次，后来发现
                                       #由于在minimize中theta的维度每次迭代都flatten一次，因此前面必须加一个reshape来保证参数向量回归原来运算需要的维度。
    theta = np.dot(X.T,(sigmoid(np.dot(X,theta))-y)) / num_X + 1 * theta / num_X
    return theta.flatten()

def main():
    data = np.array(load_data("ex2data2.txt"))
    X1 = data[:,[0]]
    X2 = data[:,[1]]
    y = data[:,[2]]
    X = X_polynomial(X1,X2)#按题目要求将多项式特征矩阵求出
    theta = np.zeros((X.shape[1], 1)).flatten()
    result = op.minimize(fun=cost_function, x0=theta, args=(X, y), method='BFGS', jac=gradient)
    theta = np.array(result["x"]).reshape(X.shape[1],1)
    X_test = np.array([[0.3, 0.3]])
    print(X_test)
    X_norm = X_polynomial(X_test[:,[0]],X_test[:,[1]])
    predict = sigmoid(X_norm.dot(theta))
    print(predict)

if __name__ == "__main__":
    main()


def calculate_depths(data, samples, lbview):
    """
    check whether mindepth has changed, and thus whether clusters_hidepth
    needs to be recalculated, and get new maxlen for new highdepth clusts.
    if mindepth not changed then nothing changes.
    """

    ## send jobs to be processed on engines
    start = time.time()
    printstr = " calculating depths    | {} | s5 |"
    recaljobs = {}
    maxlens = []
    for sample in samples:
        recaljobs[sample.name] = lbview.apply(recal_hidepth, *(data, sample))

    ## block until finished
    while 1:
        ready = [i.ready() for i in recaljobs.values()]
        elapsed = datetime.timedelta(seconds=int(time.time()-start))
        progressbar(len(ready), sum(ready), printstr.format(elapsed), spacer=data._spacer)
        time.sleep(0.1)
        if len(ready) == sum(ready):
            print("")
            break

    ## check for failures and collect results
    modsamples = []
    for sample in samples:
        if not recaljobs[sample.name].successful():
            LOGGER.error("  sample %s failed: %s", sample.name, recaljobs[sample.name].exception())
        else:
            modsample, _, maxlen, _, _ = recaljobs[sample.name].result()
            modsamples.append(modsample)
            maxlens.append(maxlen)

    ## reset global maxlen if something changed
    data._hackersonly["max_fragment_length"] = int(max(maxlens)) + 4

    return samples


from flask import Flask, request
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
import os

app = Flask(__name__)
TOKEN = os.environ.get("TOKEN")
bot = telebot.TeleBot(TOKEN)

@bot.message_handler(commands=['go'])
def gen_keyboard(message):
    keyboard = InlineKeyboardMarkup(row_width=1)
    keyboard.add(InlineKeyboardButton("Matchday", url="https://www.flashscore.ua/soccer/world/world-cup/#/2/8/zkyDYRLU/live"),
                 InlineKeyboardButton("Group", url="https://www.flashscore.ua/soccer/world/world-cup/standings/#/2/8/zkyDYRLU/table"),
                 InlineKeyboardButton("Bombardier", url="https://www.flashscore.ua/soccer/world/world-cup/standings/#/2/8/zkyDYRLU/top_scorers"),
                 InlineKeyboardButton("Results", url="https://www.flashscore.ua/soccer/world/world-cup/results/"),
                 InlineKeyboardButton("Matches", url="https://www.flashscore.ua/soccer/world/world-cup/fixtures/"))
    bot.send_message(message.chat.id, 'World Cup 2022', reply_markup=keyboard)

@bot.message_handler(commands=['start'])
def message_start(message):
    bot.send_message(f'Hello, {message.from_user.username}! \nNow i have next command:\n\n'f'/go')

@app.route("/" + TOKEN, methods=["POST"])
def get_message():
    bot.process_new_updates([telebot.types.Update.de_json(request.stream.read().decode("utf-8"))])
    return "Python Telegram Bot", 200

@app.route("/")
def main():
    bot.remove_webhook()
    bot.set_webhook(url="https://it-gen-bot.herokuapp.com/" + TOKEN)
    return "Python Telegram Bot", 200

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))


import numpy as np
import ir.framework
import ir.node
from ir.optimizer.patternmanager import NodeManager
from ir.optimizer.patterngroup import PatternGroup
from .pattern import Pattern

class Pattern17(Pattern):
    def process_pattern(
        self, node_manager: NodeManager, rule_name: str, node_map: dict
    ):
        assert len(node_map) == 1
        output_name = node_map["equal_or_unequal"].output_names[0]
        node_name = node_map["equal_or_unequal"].name + "_pattern16_identity_or_not"
        insert_index = node_manager.graph.nodes.index(node_map["equal_or_unequal"])

        if node_map["equal_or_unequal"].inputs[1].shape != [1]:
            return False
        if node_map["equal_or_unequal"].inputs[1].dtype != ir.framework.DataType.BOOL:
            return False
        if not node_map["equal_or_unequal"].inputs[1].is_constant():
            return False

        target_node_type = None
        if isinstance(node_map["equal_or_unequal"], ir.node.relation.Equal):
            if node_map["equal_or_unequal"].inputs[1].data.tolist()[0]:
                target_node_type = ir.node.base.Identity
            else:
                target_node_type = ir.node.relation.Not
        elif isinstance(node_map["equal_or_unequal"], ir.node.relation.UnEqual):
            if not node_map["equal_or_unequal"].inputs[1].data.tolist()[0]:
                target_node_type = ir.node.base.Identity
            else:
                target_node_type = ir.node.relation.Not
        else:
            raise RuntimeError("Unknow error")

        # unref

        node_manager.unrefer_node_output(node_map["equal_or_unequal"], 0)
        not_equal_node = target_node_type(
            node_name,
            node_manager.graph,
            [node_map["equal_or_unequal"].input_names[0]],
            [output_name],
        )

        node_manager.add_node(insert_index, not_equal_node)

        return True

    @property
    def pattern_group(self):
        return PatternGroup.GROUP_2


import os, re

from flask import current_app
from PIL import ImageFont, ImageDraw, Image
import requests

from .resp import APIResponse

def download_img(url):
    img_name = os.path.basename(url)
    img_dir = current_app.config["IMAGES_DIR"]
    abs_path = os.path.join(img_dir, img_name)
    with open(abs_path, 'wb') as img:
        try:
            response = requests.get(url, stream=True)
        except:
            return None

        if not response.ok:
            return None

        for block in response.iter_content(1024):
            if not block: break
            img.write(block)
    return abs_path

def download_font(url):
    font_name = os.path.basename(url)
    font_dir = current_app.config["FONTS_DIR"]
    abs_path = os.path.join(font_dir, font_name)
    with open(abs_path, 'wb') as font:
        try:
            response = requests.get(url, stream=True)
        except:
            return None

        if not response.ok:
            return None

        for block in response.iter_content(1024):
            if not block: break
            font.write(block)
    return abs_path

def get_text_and_size(box, text, font_path):
    text_lst = text['content'].split()
    # MIN 1 pixel, MAX 4K pixel
    l = 1
    r = 4096
    last_fit = None
    while l < r:
        font_size = (r - l) // 2 + l
        font = ImageFont.truetype(font_path, font_size)
        # print(f'l: {l}  r: {r}  font:{font_size}')

        words = text_lst[:]
        splits = []
        init_splite = {
            'content': '',
            'font_size': font_size,
            'x': box['x'],
            'y': box['y']
        }
        new_splite = None
        cur_h = cur_w = 0 # inbox coordinate
        new_line = True
        fit_content = False
        while words:
            word = words[0] + ' '
            word_size = get_text_dimensions(word, font)

            # if this word is the first word of line
            # record the index of the word
            if new_line:
                new_splite = init_splite.copy()
                new_splite['y'] += cur_h
                cur_h += word_size[1]
                splits.append(new_splite)
                new_line = False
                if cur_h > box['height']:
                    splits.clear()
                    fit_content = False
                    break

            # left space can't accommodate this word
            # move to next line
            cur_w += word_size[0]
            if cur_w > box['width']:
                cur_w = 0
                new_line = True
            else:
                new_splite['content'] += word
                words.pop(0)
                if not words: fit_content = True

        # if current size can fit box
        # store current result and increse font size
        if fit_content:
            last_fit = splits
            l = font_size + 1
        else:
            r = font_size

    return last_fit

def draw_content(img_path, font_path, box, colors, json_resp):
    with Image.open(img_path) as img:
        draw = ImageDraw.Draw(img)

        # draw rectangle
        shape = [
            (box['x'], box['y']),
            (box['x']+box['width'], box['y']+box['height'])
        ]
        draw.rectangle(shape, fill=None, outline=colors[0])

        # draw text
        font_size = json_resp['splits'][0]['font_size']
        font = ImageFont.truetype(font_path, font_size)
        for s in json_resp['splits']:
            draw.multiline_text(
                (s['x'], s['y']),
                s['content'],
                font=font,
                fill=colors[1]
                )

        # img.show()
        img.save(json_resp['resource'])

def gen_resp_json(image_path, font_path, box, text):
    json_resp = {}
    # resource
    resource = os.path.basename(image_path)
    resource = image_path.split('.')
    resource = f'{resource[0]}_output.{resource[1]}'
    resource  = os.path.join(current_app.config["IMAGES_DIR"], resource)
    # resource = os.path.join('D:\projects\dipp_challenge\dipp_challenge\images', resource)
    json_resp['resource'] = resource

    json_resp['splits'] = get_text_and_size(
        box, text, font_path
    )

    # print(json_resp)
    return json_resp

def get_text_dimensions(text_string, font):
    # https://stackoverflow.com/a/46220683/9263761
    ascent, descent = font.getmetrics()

    text_width = (
        font.getmask(text_string).getbbox()[2]
        + font.getlength(' ')
    )
    text_height = font.getmask(text_string).getbbox()[3] + descent

    return (text_width, text_height)

def validate_params(json_data):
    '''
    Validate all parameters.
    if not valid, return (False, statue)
    else return (True, None)
    '''
    try:
        font_url = json_data['font_url']
        image_url = json_data['image_url']
        text = json_data['text']
        content = json_data['text']['content']
        text_color = json_data['text']['text_color']
        border_color = json_data['text']['border_color']
        box = json_data['box']
        x = int(json_data['box']['x'])
        y = int(json_data['box']['y'])
        width = int(json_data['box']['width'])
        height = int(json_data['box']['height'])
    except:
        return False, APIResponse.invalid_params()

    # validate content
    if content.strip() == '': return False, APIResponse.invalid_params('content')

    # validate colors
    regex = r'^#(?:[0-9a-fA-F]{3}){1,2}$'
    if not re.match(regex, text_color) or not re.match(regex, border_color):
        return False, APIResponse.invalid_params('color')

    # validate box
    if x < 0 or y < 0 or width < 1 or height < 1:
        return False, APIResponse.invalid_params('box')

    return True, None

def box_in_img(img_path, box):
    with Image.open(img_path) as img:
        if box['x']+box['width'] > img.size[0] or box['y']+box['height'] > img.size[1]:
            return False
        return True


dict = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}

def result(A):
    output = 0
    output1 = 0
    output2 = 0
    for i in range(len(A) - 1):
        output1 += dict[A[i]]
        if dict[A[i+1]] > dict[A[i]]:
            output2 += dict[A[i]]

    output1 += dict[A[-1]]
    output = output1 - 2 * output2
    return output

input = 'MCMXCIV'

print(result(input))


class Solution:
    def islandPerimeter(self, grid: list) -> int:
        H, W = len(grid), len(grid[0])
        area = 0
        connect = 0
        for r in range(H):
            for c in range(W):
                if grid[r][c] == 1:
                    area += 1
                    if r > 0 and grid[r - 1][c] == 1:
                        connect += 1
                    if c > 0 and grid[r][c - 1] == 1:
                        connect += 1
        return area * 4 - 2 * connect

test = [[0, 1, 0, 0],
        [1, 1, 1, 0],
        [0, 1, 0, 0],
        [1, 1, 0, 0]]

a = Solution()
b = a.islandPerimeter(test)
print(b)


#!/usr/bin/env python3
# _*_ encoding: utf-8 _*_

from distutils.dir_util import copy_tree
import fileinput
import os
import shutil
import xml.etree.ElementTree as ET
from zipfile import ZipFile

PATH_BASE = os.path.dirname(__file__)
# BOOK_FNAME = 'Tom Clancy军事系列（共9册）.epub'
# BOOK_FNAME = '解密东欧：苦难与辉煌（共4册）.epub'
# BOOK_FNAME = '大家小书：大中国古典·诗词集萃（共16册）.epub'
# BOOK_FNAME = '哈耶克大全集.epub'
BOOK_FNAME = '26部欧美人文经典.epub'
SER_TITLE = '26部欧美人文经典'  # series title
PATH_TXT = 'text'  # rel path of the folder of text files
PATH_IMG = 'images'  # rel path of the folder of image files
CONT = 'content.opf'  # content file name
TOC = 'toc.ncx'  # root TOC file name
# AUTHORS = {
#     '好诗不厌百回读': '袁行霈',
#     '闲坐说诗经': '金性尧',
#     '舒芜说诗': '舒芜',
#     '唐人绝句启蒙': '李霁野',
#     '词学十讲': '龙榆生',
#     '唐宋词欣赏': '夏承焘',
#     '唐五代词境浅说': '俞陛云',
#     '诗境浅说': '俞陛云',
#     '诗论': '朱光潜',
#     '唐诗杂论': '闻一多',
#     '中国古典诗歌讲稿': '浦江清',
#     '词曲概论': '龙榆生',
#     '唐宋词启蒙': '李霁野',
#     '北宋词境浅说': '俞陛云',
#     '南宋词境浅说': '俞陛云',
#     '唐诗纵横谈': '周勋初'
# }
AUTHORS = {
    '理想国': 'Plato',
    '查拉图斯特拉如是说': 'Friedrich Nietzsche',
    '悲剧的诞生': 'Friedrich Nietzsche',
    '论美国的民主': 'Alexis de Tocqueville',
    '论人类不平等的起源和基础': 'Jean-Jacques Rousseau',
    '菊与刀': 'Ruth Benedict',
    '国富论': 'Adam Smith',
    '富兰克林自传': 'Benjamin Franklin',
    '人性的弱点': 'Dale Carnegie',
    '论自由': 'John Stuart Mill',
    '宽容': 'Hendrik Willem van Loon',
    '思想录': 'Blaise Pascal',
    '战争论': 'Carl von Clausewitz',
    '物种起源': 'Charles Darwin',
    '审美教育书简': 'Friedrich Schiller',
    '论道德原理·论人类理智': 'David Hume',
    '道德情操论': 'Adam Smith',
    '愚人颂': 'Erasmus',
    '方法论·情志论': 'René Descartes',
    '物性论': 'Lucretius',
    '论共和国': 'Cicero',
    '自然史': 'Buffon',
    '西绪福斯神话': 'Albert Camus',
    '孤独漫步者的遐想': 'Jean-Jacques Rousseau',
    '人生的意义与价值': 'Rudolf Christoph Eucken',
    '社会契约论': 'Jean-Jacques Rousseau'
}

class EpubBook(object):
    """ The class for e-books in epub format

    This class has attributes describing the ebook instance. Example:
    self.fname_full: <full path>\\Tom Clancy军事系列（共9册）.epub
    self.path: <full path>
    self.fname: Tom Clancy军事系列（共9册）
    self.fname_ext: .epub
    self.title: ''
    self.author: ''
    self.file_cont = 'content.opf'
    self.file_toc = 'toc.ncx'
    self.path_img: Tom Clancy军事系列（共9册）\\images
    self.files_img: ['00001.jpeg',]
    self.file_img_cover: 00029.jpeg
    self.path_txt: Tom Clancy军事系列（共9册）\\text
    self.files_txt: ['part0000.html',]
    self.file_txt_toc: part0001.html
    """
    def __init__(self, fname_full):
        self.fname_full = fname_full
        self.path, file_name = os.path.split(fname_full)
        self.fname, self.fname_ext = os.path.splitext(file_name)
        self.title = ''
        self.author = ''
        self.file_cont = CONT  # name of the content file
        self.file_toc = TOC  # name of the root TOC file
        self.path_img = os.path.join(self.fname, PATH_IMG)
        self.files_img = []
        self.file_img_cover = ''  # filename of cover img
        self.path_txt = os.path.join(self.fname, PATH_TXT)
        self.files_txt = []
        self.file_txt_toc = ''  # the toc file in the text folder
        if self.path:
            os.chdir(self.path)

    def unzip_book(self):
        fname_zip = self.fname + '.zip'
        shutil.copy2(self.fname + self.fname_ext, fname_zip)
        os.makedirs(self.fname)
        with ZipFile(fname_zip) as f:
            f.extractall(self.fname)
        os.remove(fname_zip)

    def __get_file_img_cover(self):
        """ read content file to update self.file_img_cover """
        os.chdir(self.fname)
        tree = ET.parse(self.file_cont)
        root = tree.getroot()

        # update namespace
        ns = {'dft': ''}
        if root.tag.startswith('{'):
            ns['dft'] = root.tag.split('}')[0].strip('{')

        root_manifest = root.find('dft:manifest', ns)
        root_manifest_items = root_manifest.findall('dft:item', ns)
        for item in root_manifest_items:
            id = item.get('id')
            mtype = item.get('media-type')
            if id == 'cover' and mtype == 'image/jpeg':
                self.file_img_cover = item.get('href').split('/')[1]
                break

        os.chdir(self.path)

    def get_book_info(self):
        """ update book info, including:
        self.files_img,
        self.files_txt,
        self.file_txt_toc,
        self.file_img_cover (by calling __get_file_img_cover())
        """
        self.__get_file_img_cover()

        for f in os.listdir(self.path_img):
            self.files_img.append(f)
        for f in os.listdir(self.path_txt):
            self.files_txt.append(f)

        # find the toc file in the text folder
        brk = False
        for fn in self.files_txt:
            target = os.path.join(self.path_txt, fn)
            with open(target, 'r') as f:
                fc = f.readlines()
                for line in fc:
                    if '总 目 录' in line or '总目录' in line \
                            or '目  录' in line or '目录' in line:
                        self.file_txt_toc = fn
                        brk = True
                        break
            if brk:
                break

    def write_book_info(self, fname):
        with open(fname, 'a+') as f:
            f.write()

class EpubBundle(EpubBook):
    """ The special type of epub book that has multiple epub books bundled

    self.subbooks is a list of subbooks, which have following keys:
    'title', 'author', 'ser_idx',
    'file_img_top', 'file_img_top_idx'
    'file_img_end', 'files_img_num'
    'file_txt_top', 'file_txt_top_idx'
    'file_txt_end', 'files_txt_num'

    A subbook example:
    {'title': '冷血悍将',
     'author': '周勋初',
     'ser_idx': '01',
     'file_img_top': '00017.jpeg',
     'file_img_top_idx': 16,
     'file_img_end': '00019.jpeg',
     'files_img_num': 3,
     'file_txt_top': 'part0186.html',
     'file_txt_top_idx': 186,
     'file_txt_end': 'part0234.html',
     'files_txt_num': 49}

     self.comm_items is a list of common items, which have following keys:
     'title', 'file_txt_top'

     A comm_items example:
     [{'file_txt_top': 'part0000.html', 'title': '版权信息'},
      {'file_txt_top': 'part0001.html', 'title': '总目录'}]
    """
    def __init__(self, fname_full, ser_title):
        super().__init__(fname_full)
        self.title = ser_title
        self.subbooks = []
        # self.comm_items = []  # common items, e.g. '版权信息', '总目录'
        self.comm_items = [{'file_txt_top': 'part0000.html', 'title': '目录'}]
        self.files_txt_comm_num = 0  # number of text files for common items
        self.files_img_cover_num = 1  # for self.file_img_cover

    def __parse_toc_ncx(self, fname='toc.ncx'):
        os.chdir(self.fname)

        tree = ET.parse(fname)
        root = tree.getroot()

        ns = {'dft': ''}
        if root.tag.startswith('{'):
            ns['dft'] = root.tag.split('}')[0].strip('{')

        root_navMap = root.find('dft:navMap', ns)
        root_navMap_navPoints = root_navMap.findall('dft:navPoint', ns)
        for navPoint in root_navMap_navPoints:
            item = {}

            navPoint_content = navPoint.find('dft:content', ns)
            src = navPoint_content.get('src')
            item['file_txt_top'] = src.split('#')[0].rsplit('/', 1)[1]

            navPoint_navLabel = navPoint.find('dft:navLabel', ns)
            navPoint_navLabel_text = navPoint_navLabel.find('dft:text', ns)
            item['title'] = navPoint_navLabel_text.text

            # if item['title'] in ['版权信息', '总目录']:
            if item['title'] in ['扉页', '目录']:
                self.comm_items.append(item)
            else:
                self.subbooks.append(item)

        os.chdir(self.path)

    def __get_subbook_img_top(self):
        for book in self.subbooks:
            target = os.path.join(self.path_txt, book['file_txt_top'])
            with open(target, 'r') as f:
                fc = f.readlines()  # file content
                for _l in fc:
                    if 'jpeg' in _l:
                        book['file_img_top'] = \
                            _l.split('src="')[1].split('"', 1)[0].\
                            rsplit('/', 1)[1]

    def __get_subbook_end(self):
        """ get subbook info for both image and text files.

        The info includes:
        'file_img_top_idx', 'file_img_end', 'files_img_num'
        'file_txt_top_idx', 'file_txt_end', 'files_txt_num'
        """
        self.subbooks[0]['file_img_top_idx'] = self.files_img.index(
            self.subbooks[0]['file_img_top'])
        self.subbooks[0]['file_txt_top_idx'] = self.files_txt.index(
            self.subbooks[0]['file_txt_top'])

        for idx in range(len(self.subbooks) - 1):
            book_curr = self.subbooks[idx]
            book_next = self.subbooks[idx + 1]

            book_next['file_img_top_idx'] = self.files_img.index(
                book_next['file_img_top'])
            book_next['file_txt_top_idx'] = self.files_txt.index(
                book_next['file_txt_top'])

            book_curr['file_img_end'] = self.files_img[
                book_next['file_img_top_idx'] - 1]
            book_curr['files_img_num'] = book_next['file_img_top_idx'] - \
                book_curr['file_img_top_idx']

            book_curr['file_txt_end'] = self.files_txt[
                book_next['file_txt_top_idx'] - 1]
            book_curr['files_txt_num'] = book_next['file_txt_top_idx'] - \
                book_curr['file_txt_top_idx']

        self.subbooks[-1]['file_img_end'] = self.files_img[-2]
        # the last img is for bundle cover
        self.subbooks[-1]['files_img_num'] = len(self.files_img) - 1 - \
            self.subbooks[-1]['file_img_top_idx']

        self.subbooks[-1]['file_txt_end'] = self.files_txt[-1]
        self.subbooks[-1]['files_txt_num'] = len(self.files_txt) - \
            self.subbooks[-1]['file_txt_top_idx']

    def __get_files_txt_comm_num(self):
        idx_top = self.files_txt.index(self.comm_items[0]['file_txt_top'])
        idx_end = self.files_txt.index(self.subbooks[0]['file_txt_top'])
        self.files_txt_comm_num = idx_end - idx_top

    def get_subbook_info(self):
        self.__parse_toc_ncx()
        self.__get_subbook_img_top()
        self.__get_subbook_end()

        self.__get_files_txt_comm_num()
        tot_img = 0
        tot_txt = 0
        for book in self.subbooks:
            book['author'] = AUTHORS[book['title']]
            idx = list(AUTHORS.keys()).index(book['title'])
            book['ser_idx'] = '{:02}'.format(idx + 1)
            tot_img += book['files_img_num']
            tot_txt += book['files_txt_num']
        assert tot_img + self.files_img_cover_num == len(self.files_img)
        assert tot_txt + self.files_txt_comm_num == len(self.files_txt)

    def __parse_and_get_ns(self, file):
        events = "start", "start-ns"
        root = None
        ns = {}
        for event, elem in ET.iterparse(file, events):
            if event == "start-ns":
                if elem[0] in ns and ns[elem[0]] != elem[1]:
                    # NOTE: It is perfectly valid to have the same prefix refer
                    # to different URI namespaces in different parts of the
                    # document. This exception serves as a reminder that this
                    # solution is not robust. Use at your own peril.
                    raise KeyError("Same prefix with different URI found.")
                # ns[elem[0]] = "{%s}" % elem[1]
                ns[elem[0]] = elem[1]
            elif event == "start":
                if root is None:
                    root = elem
        return ns

    def __create_file_txt_toc(self, path_book):
        path_work, title = os.path.split(path_book)
        fname_ori = os.path.join(self.fname, PATH_TXT, self.file_txt_toc)
        fname_new = os.path.join(path_book, PATH_TXT, self.file_txt_toc)

        tree = ET.parse(fname_ori)
        root = tree.getroot()

        ns = self.__parse_and_get_ns(fname_ori)
        ns['dft'] = ns['']

        root_body = root.find('dft:body', ns)
        root_body_ps = root_body.findall('dft:p', ns)
        for p in root_body_ps:
            p_a = p.find('dft:a', ns)
            if p_a.text != title:
                # delete attrib 'href'
                del p_a.attrib['href']

        ET.register_namespace("", ns['dft'])
        tree.write(fname_new, encoding='utf-8', xml_declaration=True)

    def __create_subbook_cont(self, path_book, author_new, ser_idx):
        path_work, title_new = os.path.split(path_book)
        path_img = os.path.join(path_book, PATH_IMG)
        path_txt = os.path.join(path_book, PATH_TXT)

        fname_ori = os.path.join(self.fname, CONT)
        fname_new = os.path.join(path_book, CONT)

        tree = ET.parse(fname_ori)
        root = tree.getroot()

        ns = self.__parse_and_get_ns(fname_ori)
        ns['dft'] = ns['']

        # the metadata part
        root_metadata = root.find('dft:metadata', ns)

        # to overwrite the text for root_metadata_title
        root_metadata_title = root_metadata.find('dc:title', ns)
        root_metadata_title.text = title_new

        # to overwrite the text for root_metadata_creator
        root_metadata_creators = root_metadata.findall('dc:creator', ns)
        key = '{%s}file-as' % ns['opf']
        for cre in root_metadata_creators:
            if cre.text == author_new:
                cre.set(key, author_new)
            else:
                root_metadata.remove(cre)

        # to add <meta name="calibre:series", <meta name="calibre:series_index"
        root_metadata_ser = ET.SubElement(root_metadata, 'meta')
        root_metadata_ser.set('name', 'calibre:series')
        root_metadata_ser.set('content', self.title)

        root_metadata_ser = ET.SubElement(root_metadata, 'meta')
        root_metadata_ser.set('name', 'calibre:series_index')
        root_metadata_ser.set('content', ser_idx)

        # the manifest part
        keep_list_img = os.listdir(path_img)
        keep_list_txt = os.listdir(path_txt)
        keep_list_id = ['titlepage']
        root_manifest = root.find('dft:manifest', ns)
        root_manifest_items = root_manifest.findall('dft:item', ns)
        for item in root_manifest_items:
            href = item.get('href')
            if href.startswith('images'):
                fn = href.split('/', 1)[1]
                if fn not in keep_list_img:
                    root_manifest.remove(item)
            elif href.startswith('text'):
                fn = href.split('/', 1)[1]
                if fn not in keep_list_txt:
                    root_manifest.remove(item)
                else:
                    keep_list_id.append(item.get('id'))
            else:
                continue

        # the spine part
        root_spine = root.find('dft:spine', ns)
        root_spine_itemrefs = root_spine.findall('dft:itemref', ns)
        for item in root_spine_itemrefs:
            if item.get('idref') not in keep_list_id:
                root_spine.remove(item)

        # the guide part
        # root_guide = root.find('dft:guide', ns)
        # root_guide_refs = root_guide.findall('dft:reference', ns)
        # for ref in root_guide_refs:
        #     if ref.get('title') not in ['Cover', '目录']:
        #         ref.set('title', title_new)

        ET.register_namespace("", ns['dft'])
        tree.write(fname_new, encoding='utf-8', xml_declaration=True)

    def __create_subbook_toc(self, path_book):
        path_work, title_new = os.path.split(path_book)
        fname_ori = os.path.join(self.fname, TOC)
        fname_new = os.path.join(path_book, TOC)

        tree = ET.parse(fname_ori)
        root = tree.getroot()

        ns = {'dft': ''}
        if root.tag.startswith('{'):
            ns['dft'] = root.tag.split('}')[0].strip('{')

        # to update root_docTitle_text with title_new
        root_docTitle = root.find('dft:docTitle', ns)
        root_docTitle_text = root_docTitle.find('dft:text', ns)
        root_docTitle_text.text = title_new

        # the navMap part
        root_navMap = root.find('dft:navMap', ns)
        root_navMap_navPoints = root_navMap.findall('dft:navPoint', ns)
        for navPoint in root_navMap_navPoints:
            # keep_list = ['版权信息', '总目录', title_new]
            # keep_list = ['扉页', '目录', title_new]
            keep_list = [title_new]

            navPoint_navLabel = navPoint.find('dft:navLabel', ns)
            navPoint_navLabel_text = navPoint_navLabel.find('dft:text', ns)

            # to remove any navPoint other than booktitle
            if navPoint_navLabel_text.text not in keep_list:
                root_navMap.remove(navPoint)

        ET.register_namespace("", ns['dft'])
        tree.write(fname_new, encoding='utf-8', xml_declaration=True)

        with fileinput.FileInput(fname_new, inplace=True) as f:
            for line in f:
                print(line.replace('    </navMap>', '  </navMap>'), end='')

    def create_subbook(self):
        path_work = 'working'
        os.mkdir(path_work)
        for book in self.subbooks:
            path_book = os.path.join(path_work, book['title'])
            path_book_img = os.path.join(path_book, PATH_IMG)
            path_book_txt = os.path.join(path_book, PATH_TXT)
            # create book folder, and sub-folders: images, text
            os.mkdir(path_book)
            while True:
                if os.path.exists(path_book):
                    os.mkdir(path_book_img)
                    os.mkdir(path_book_txt)
                    break

            # copy img files of each book, plus the bundle cover img
            src_cover = os.path.join(self.path_img, self.file_img_cover)
            dst_cover = os.path.join(path_book_img, self.file_img_cover)
            shutil.copy2(src_cover, dst_cover)

            for i in range(book['files_img_num']):
                idx = book['file_img_top_idx'] + i
                src_img = os.path.join(self.path_img, self.files_img[idx])
                dst_img = os.path.join(path_book_img, self.files_img[idx])
                shutil.copy2(src_img, dst_img)

            num_img = len(os.listdir(path_book_img))
            assert num_img == book['files_img_num'] + self.files_img_cover_num

            # copy txt files of each book, plus the commom txt files
            for i in range(book['files_txt_num']):
                idx = book['file_txt_top_idx'] + i
                src_txt = os.path.join(self.path_txt, self.files_txt[idx])
                dst_txt = os.path.join(path_book_txt, self.files_txt[idx])
                shutil.copy2(src_txt, dst_txt)

            for item in self.comm_items:
                if item['file_txt_top'] == self.file_txt_toc:
                    self.__create_file_txt_toc(path_book)
                else:
                    src_txt = os.path.join(self.path_txt, item['file_txt_top'])
                    dst_txt = os.path.join(path_book_txt, item['file_txt_top'])
                    shutil.copy2(src_txt, dst_txt)

            num_txt = len(os.listdir(path_book_txt))
            assert num_txt == book['files_txt_num'] + self.files_txt_comm_num

            # copy META-INF from bundle book to subbook
            src = os.path.join(self.fname, 'META-INF')
            dst = os.path.join(path_book, 'META-INF')
            copy_tree(src, dst)

            # copy all files from bundle book to subbook
            files = [f for f in os.listdir(self.fname) if os.path.isfile(
                os.path.join(self.fname, f))]
            for f in files:
                if f in ['toc.ncx', 'content.opf']:
                    continue
                src = os.path.join(self.fname, f)
                dst = os.path.join(path_book, f)
                shutil.copy2(src, dst)

            # modify content.opf
            self.__create_subbook_cont(
                path_book, book['author'], book['ser_idx'])

            # modify toc.ncx
            self.__create_subbook_toc(path_book)

            # create zip file, copy to epub file, remove zip file
            os.chdir(path_work)
            shutil.make_archive(book['title'], 'zip', book['title'])
            shutil.copy2('{0}.zip'.format(book['title']), '{0} - {1}.epub'.
                         format(book['author'], book['title']))
            os.remove('{0}.zip'.format(book['title']))
            os.chdir(self.path)

def main():
    my_book = EpubBundle(os.path.join(PATH_BASE, BOOK_FNAME), SER_TITLE)
    # my_book.unzip_book()
    my_book.get_book_info()
    my_book.get_subbook_info()
    my_book.create_subbook()

if __name__ == '__main__':
    main()


import pygame
from game_object import GameObject
from bullet import Bullet

class Player(GameObject):

	speed = [0,0]
	soundManager = None
	canFire = True
	fireTimer = 0
	fireInterval = 60
	gameManager = None

	#Start Function, runs once upon initialization of the object
	def start(self):
		self.soundManager = self._game.getGameObjectByName("SoundManager")
		self.gameManager = self._game.getGameObjectByName("GameManager")
	#Update function, runs once every clock tick
	def update(self):
		if not self.gameManager == None:
			if self.gameManager.playing:
				kd = self._game.findEvent(pygame.KEYDOWN)
				ku = self._game.findEvent(pygame.KEYUP)
				key = None
				if not self.canFire:
					if self.fireTimer < (self.fireInterval / (self.gameManager.waveCount + 1)):
						self.fireTimer += 1
					else:
						self.canFire = True
						self.fireTimer = 0

				if not kd == None:
					key = kd.__dict__.get('key')
					if key == pygame.K_a:
						if self._bounds.left > 0:
							self.speed = [-5,0]
						else:
							self.speed = [0,0]
					if key == pygame.K_d:
						if self._bounds.right < self._game._size[0]:
							self.speed = [5,0]
						else:
							self.speed = [0,0]

					if key == pygame.K_SPACE:
						if self.canFire:
							self.canFire = False
							#self.soundManager.play_sound("laser.wav")
							self._game.instantiate(Bullet(self._game,"Bullet","bullet.png",self._bounds.x + 10,self._bounds.y - 20))

				if not ku == None:
					key = ku.__dict__.get('key')
					if key == pygame.K_a:
						self.speed = [0,0]
					if key == pygame.K_d:
						self.speed = [0,0]
		else:
			self.gameManager = self._game.getGameObjectByName("GameManager")

		self._bounds = self._bounds.move(self.speed)


''''
    This is a framework test for a wargame project.
    It is not intended to be a complete game, but rather a test of the framework.
'''
import json
import pygame
# pylint: disable=too-many-locals
WIDTH = 1200
HEIGHT = 900

GAME_WIDTH = 800
GAME_HEIGHT = 640
GAME_WINDOW_X = 10
GAME_WINDOW_Y = 250

TITLE_WIDTH = 800
TITLE_HEIGHT = 230
TITLE_WINDOW_X = 10
TITLE_WINDOW_Y = 10

MENU_WIDTH = 370
MENU_HEIGHT = 880
MENU_WINDOW_X = 820
MENU_WINDOW_Y = 10

GRAY = (128, 128, 128)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BROWN = (165, 42, 42)

FONTDATA = "y:/Resources/development/data/Fontdata.json"
TILE_WIDTH = 64
TILE_HEIGHT = 64

GRASS_TILE_01 = pygame.image.load('y:/Resources/development/game-assets/tiles/grass001.png')
GRASS_TILE_02 = pygame.image.load('y:/Resources/development/game-assets/tiles/grass002.png')
GRASS_TILE_03 = pygame.image.load('y:/Resources/development/game-assets/tiles/grass003.png')
DIRT_TILE_01 = pygame.image.load('y:/Resources/development/game-assets/tiles/dirt001.png')
DIRT_TILE_02 = pygame.image.load('y:/Resources/development/game-assets/tiles/dirt002.png')
SAND_TILE_01 = pygame.image.load('y:/Resources/development/game-assets/tiles/sand001.png')
SAND_TILE_02 = pygame.image.load('y:/Resources/development/game-assets/tiles/sand002.png')
STONE_TILE_01 = pygame.image.load('y:/Resources/development/game-assets/tiles/stone001.png')
STONE_TILE_02 = pygame.image.load('y:/Resources/development/game-assets/tiles/stone002.png')
STONE_TILE_03 = pygame.image.load('y:/Resources/development/game-assets/tiles/stone003.png')
WATER_TILE_01 = pygame.image.load('y:/Resources/development/game-assets/tiles/water001.png')
WATER_TILE_02 = pygame.image.load('y:/Resources/development/game-assets/tiles/water002.png')
WATER_TILE_03 = pygame.image.load('y:/Resources/development/game-assets/tiles/water003.png')
WATER_TILE_04 = pygame.image.load('y:/Resources/development/game-assets/tiles/water004.png')
WATER_BOTTOM = pygame.image.load('y:/Resources/development/game-assets/tiles/water-bottom.png')
WATER_BOTTOM_RIGHT = pygame.image.load('y:/Resources/development/game-assets/tiles/water-bottomright.png')
WATER_BOTTOM_LEFT = pygame.image.load('y:/Resources/development/game-assets/tiles/water-bottomleft.png')
WATER_LEFT = pygame.image.load('y:/Resources/development/game-assets/tiles/water-left.png')
WATER_RIGHT = pygame.image.load('y:/Resources/development/game-assets/tiles/water-right.png')
WATER_TOP = pygame.image.load('y:/Resources/development/game-assets/tiles/water-top.png')
WATER_TOP_LEFT = pygame.image.load('y:/Resources/development/game-assets/tiles/water-topleft.png')
WATER_TOP_RIGHT = pygame.image.load('y:/Resources/development/game-assets/tiles/water-topright.png')

TILES = []
TILES.append(pygame.transform.scale(GRASS_TILE_01, (TILE_WIDTH, TILE_HEIGHT))) # 0
TILES.append(pygame.transform.scale(GRASS_TILE_02, (TILE_WIDTH, TILE_HEIGHT))) # 1
TILES.append(pygame.transform.scale(GRASS_TILE_03, (TILE_WIDTH, TILE_HEIGHT))) # 2
TILES.append(pygame.transform.scale(DIRT_TILE_01, (TILE_WIDTH, TILE_HEIGHT))) # 3
TILES.append(pygame.transform.scale(DIRT_TILE_02, (TILE_WIDTH, TILE_HEIGHT))) # 4
TILES.append(pygame.transform.scale(SAND_TILE_01, (TILE_WIDTH, TILE_HEIGHT))) # 5
TILES.append(pygame.transform.scale(SAND_TILE_02, (TILE_WIDTH, TILE_HEIGHT))) # 6
TILES.append(pygame.transform.scale(STONE_TILE_01, (TILE_WIDTH, TILE_HEIGHT))) # 7
TILES.append(pygame.transform.scale(STONE_TILE_02, (TILE_WIDTH, TILE_HEIGHT))) # 8
TILES.append(pygame.transform.scale(STONE_TILE_03, (TILE_WIDTH, TILE_HEIGHT))) # 9
TILES.append(pygame.transform.scale(WATER_TILE_01, (TILE_WIDTH, TILE_HEIGHT))) # 10
TILES.append(pygame.transform.scale(WATER_TILE_02, (TILE_WIDTH, TILE_HEIGHT))) # 11
TILES.append(pygame.transform.scale(WATER_TILE_03, (TILE_WIDTH, TILE_HEIGHT))) # 12
TILES.append(pygame.transform.scale(WATER_TILE_04, (TILE_WIDTH, TILE_HEIGHT))) # 13
TILES.append(pygame.transform.scale(WATER_BOTTOM, (TILE_WIDTH, TILE_HEIGHT))) # 14
TILES.append(pygame.transform.scale(WATER_BOTTOM_RIGHT, (TILE_WIDTH, TILE_HEIGHT))) # 15
TILES.append(pygame.transform.scale(WATER_BOTTOM_LEFT, (TILE_WIDTH, TILE_HEIGHT))) # 16
TILES.append(pygame.transform.scale(WATER_LEFT, (TILE_WIDTH, TILE_HEIGHT))) # 17
TILES.append(pygame.transform.scale(WATER_RIGHT, (TILE_WIDTH, TILE_HEIGHT))) # 18
TILES.append(pygame.transform.scale(WATER_TOP, (TILE_WIDTH, TILE_HEIGHT))) # 19
TILES.append(pygame.transform.scale(WATER_TOP_LEFT, (TILE_WIDTH, TILE_HEIGHT))) # 20
TILES.append(pygame.transform.scale(WATER_TOP_RIGHT, (TILE_WIDTH, TILE_HEIGHT))) # 21

GAMEMAP = [[0,0,0,0,0,0,0,0,0,0,0,0],
           [0,1,2,0,2,1,0,2,1,0,2,1],
           [0,8,9,8,9,8,9,8,9,8,9,0],
           [0,3,4,3,4,3,4,3,4,3,4,0],
           [0,20,19,19,19,19,19,19,19,19,21,0],
           [0,17,10,11,10,11,10,11,10,11,18,0],
           [0,16,14,14,14,14,14,14,14,14,15,0],
           [0,5,6,5,6,5,6,5,6,5,6,0],
           [0,2,1,0,2,0,1,2,1,1,2,0],
           [0,0,0,0,0,0,0,0,0,0,0,0],]

def build_map( width, height):
    '''Build the map'''
    returnmap = []
    for y in range(height):
        row = []
        for x in range(width):
            row.append(0)
        returnmap.append(row)
    return returnmap

def main():
    '''Main function'''
    # Initialise pygame
    pygame.init()
    pygame.font.init()

    window = pygame.display.set_mode((WIDTH, HEIGHT))
    clock = pygame.time.Clock()
    pygame_icon = pygame.image.load('y:/Resources/jackmanimation.png')
    caption = "Wargame Test"
    pygame.display.set_caption(f"{caption}")
    pygame.display.set_icon(pygame_icon)

    game_window = pygame.Surface((GAME_WIDTH, GAME_HEIGHT))
    title_window = pygame.Surface((TITLE_WIDTH, TITLE_HEIGHT))
    menu_window = pygame.Surface((MENU_WIDTH, MENU_HEIGHT))

    listfonts= pygame.font.get_fonts()

    titlefont = pygame.font.SysFont('footlight', 24)
    titletext = titlefont.render('Title information is here', True, BLACK, GRAY)
    titletext_rect = titletext.get_rect()
    titletextwidth = titletext_rect.width

    menufont = pygame.font.SysFont('couriernew', 30)
    menutext = menufont.render('Menu Items', True, WHITE, BROWN)
    menutext_rect = menutext.get_rect()
    menutextwidth = menutext_rect.width

    infofont = pygame.font.SysFont('couriernew', 20)
    # Main Game loop
    run = True
    info = "Mouse not pressed"
    while run:
        mousepos = pygame.mouse.get_pos()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    run = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                info = f"Mouse pressed at  x:{mousepos[0]} y:{mousepos[1]}"
            elif event.type == pygame.MOUSEBUTTONUP:
                info = f"Mouse released at  x:{mousepos[0]} y:{mousepos[1]}"

        infotext = infofont.render(info, True, WHITE, BROWN)
        mousetext = infofont.render(f"Mouse at x:{mousepos[0]} y:{mousepos[1]}", True, WHITE, BROWN)
        maptext = infofont.render(f"Map is {len(GAMEMAP[0])}:Wide x {len(GAMEMAP)}:High", True, WHITE, BROWN )
        spritetext = infofont.render(f"Sprite is {TILES[0].get_width()}:Wide x {TILES[0].get_height()}:High", True, WHITE, BROWN )
        tiletext = infofont.render(f"map is {len(GAMEMAP[0])}:Wide x {len(GAMEMAP)}:High", True, WHITE, BROWN )

        clock.tick(100)
        window.fill((WHITE))
        game_window.fill((BLACK))
        title_window.fill((GRAY))
        menu_window.fill((BROWN))

        for y in range(len(GAMEMAP)):
            for x in range(len(GAMEMAP[y])):
                game_window.blit(TILES[GAMEMAP[y][x]], (x*TILES[0].get_width(), y*TILES[0].get_height()))

        title_window.blit(titletext, (TITLE_WIDTH//2-titletextwidth//2, 10))

        menu_window.blit(menutext, (MENU_WIDTH//2-menutextwidth//2, 10))
        menu_window.blit(infotext, (10, 50))
        menu_window.blit(mousetext, (10, 70))
        menu_window.blit(maptext, (10, 90))
        menu_window.blit(spritetext, (10, 110))
        menu_window.blit(tiletext, (10, 130))

        window.blit(game_window, (GAME_WINDOW_X, GAME_WINDOW_Y))
        window.blit(title_window, (TITLE_WINDOW_X, TITLE_WINDOW_Y))
        window.blit(menu_window, (MENU_WINDOW_X, MENU_WINDOW_Y))

        pygame.display.update()

    # finish the game and quit
    pygame.quit()
    with open(f"{FONTDATA}", "w", encoding='utf-8-sig') as file:
        json.dump({"pygame_fonts": listfonts,},
                  file,
                  indent=4,
                  ensure_ascii=False)

if __name__ == "__main__":
    main()


# ""Self Destruct""
# Write a script that makes HTTP requests to the server
# http://127.0.0.1:8082/selfdestruct until the numbers match
# and read the response to get the flag.
# You can easily run out of execution time in this challenge.
# You will need to check the response and stop your attack
# once you see the flag.
#
import urllib.request

url = 'http://127.0.0.1:8082/selfdestruct'

while True:
	res = urllib.request.urlopen(url)
	data = str(res.read(), 'utf-8')
	if 'Win: ' in data:
		print(data)
		break


# 골드 4레벨        최소 스패닝 트리
# 크루스칼 알고리즘
# 유니온 파인드
import sys

V, S = map(int, sys.stdin.readline().split())

edge = []
for _ in range(S):
    a, b, w = map(int, sys.stdin.readline().split())
    edge.append((w, a, b))
edge.sort(key=lambda x: x[0])
parent = list(range(V + 1))

# range 1~ 안댐

def connect(a, b):
    a = check(a)
    b = check(b)

    if b < a:
        parent[a] = b
    else:
        parent[b] = a

def check(a):
    if a == parent[a]:
        return a
    parent[a] = check(parent[a])  # 경로 압축
    return parent[a]  # check(parent[a])

sum = 0
for w, s, e in edge:
    if check(s) != check(e):
        connect(s, e)
        sum += w

print(sum)


"""plan item

Revision ID: 9a86d42a4063
Revises: 9489d8be8808
Create Date: 2023-08-17 17:42:16.495358

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '9a86d42a4063'
down_revision = '9489d8be8808'
branch_labels = None
depends_on = None

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('plan_item',
    sa.Column('sender', sa.Float(), nullable=False),
    sa.Column('receiver', sa.Float(), nullable=False),
    sa.Column('sub1', sa.String(length=800), nullable=True),
    sa.Column('sub2', sa.String(length=800), nullable=True),
    sa.Column('source_id', sa.Integer(), nullable=False),
    sa.Column('updated_at', sa.TIMESTAMP(timezone=True), nullable=False),
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.ForeignKeyConstraint(['source_id'], ['source.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('plan_item')
    # ### end Alembic commands ###


import os
import subprocess
import sys
from types import SimpleNamespace

import cv2
import numpy as np
from PIL import Image, ImageColor
from pathlib import Path
import torchvision.transforms

from settings import CLASS_NAMES, CLASS_MAPS, GRID
from parse_image.utils.noise_utils import generate_perlin_noise
from parse_image.utils.misc import is_image

LABEL_VIZ = SimpleNamespace(
    rows=GRID.height,
    cols=GRID.width,
    cell_size=60,
    cell_padding=5,
    cell_padding_color='#808080',
    # scale_factor=0.9, # account for the bg of the training images
)
def get_img_size(rows, cols, cell_size, padding):
    return SimpleNamespace(
        height=(cell_size + padding) * rows + padding,
        width=(cell_size + padding) * cols + padding,
    )
VIZ_IMG_SIZE = get_img_size(
    rows=LABEL_VIZ.rows,
    cols=LABEL_VIZ.cols,
    cell_size=LABEL_VIZ.cell_size,
    padding=LABEL_VIZ.cell_padding,
)

def get_class_color(name):
    return CLASS_MAPS.name_to_color[name]

def hex_to_cv2_color(hex_color):
    r, g, b = ImageColor.getrgb(hex_color)
    bgr = (b, g, r)
    return bgr

def pad_img(img, target_size, fill=(0,0,0)):
    h, w = img.shape[:2]
    pad_height = max(target_size[0] - h, 0)
    pad_width = max(target_size[1] - w, 0)

    pad_top = pad_height // 2
    pad_bot = pad_height - pad_top

    pad_left = pad_width // 2
    pad_right = pad_width - pad_left

    padding = (pad_left, pad_top, pad_right, pad_bot)
    pad_fn = torchvision.transforms.Pad(padding, fill=fill)
    return np.array(pad_fn(Image.fromarray(img)))

# NOTE: Not using this currently...
# May want something like this if we attempt the hard method again.
def combine_images(img1, img2, padding=20, bg_color='#000'):
    height1, height2 = img1.shape[0], img2.shape[0]

    # Calculate the padding for top and bottom to center the image
    diff = abs(height1 - height2)
    pad_top = diff // 2
    pad_bot = diff - pad_top

    # Create padding between the images
    color = hex_to_cv2_color(bg_color)
    horiz_padding_dim = (max(height1, height2), padding, 3)
    horiz_padding_img = np.full(horiz_padding_dim, color, dtype=np.uint8)

    # Pad the smaller image so it matches size of larger image
    if height1 < height2:
        img1 = pad_img(img1, img2.shape[:2], fill=color)
    else:
        img2 = pad_img(img2, img1.shape[:2], fill=color)

    # Concatenate the images horizontally
    return np.hstack((img1, horiz_padding_img, img2))

def load_label_or_noop(label_path_or_content):
    if os.path.exists(label_path_or_content):
        with open(label_path_or_content, 'r') as f:
            return f.read()
    return label_path_or_content

def get_class_counts(labels):
    content = load_label_or_noop(labels)
    lines = content.splitlines()
    flat_labels = ''.join([
        line.lower() for line in lines if (line and line[0] != '#')
    ])
    return { c: flat_labels.count(c) for c in CLASS_NAMES }

def validate_labels(labels):
    content = load_label_or_noop(labels)
    if len(content.strip()) == 0:
        return False
    counts = get_class_counts(content)
    return all(count == 5 for name, count in counts.items())

def make_textured_color_block(size, base_color):
    block_shape = (size, size)
    texture = generate_perlin_noise(block_shape, scale=0.02)
    texture_bgr = cv2.cvtColor(texture, cv2.COLOR_GRAY2BGR)
    plain_block = np.full((*block_shape, 3), base_color, dtype=texture.dtype)

    # blend the Perlin noise texture with the base color
    alpha = 0.95
    return cv2.addWeighted(plain_block, alpha, texture_bgr, 1 - alpha, 0)

def visualize_labels(label_path):
    with open(label_path, 'r') as f:
        lines = [line.strip() for line in f.read().strip().splitlines()]

    labels = [line.split(' ') for line in lines if line and line[0] != '#']

    img_size = (VIZ_IMG_SIZE.height, VIZ_IMG_SIZE.width, 3)
    viz_img = np.full(
        img_size,
        hex_to_cv2_color(LABEL_VIZ.cell_padding_color),
        dtype=np.uint8,
    )

    size = LABEL_VIZ.cell_size
    cell_padding = LABEL_VIZ.cell_padding

    for i in range(LABEL_VIZ.rows):
        for j in range(LABEL_VIZ.cols):
            top_left = dict(
                y = i * (size + cell_padding) + cell_padding,
                x = j * (size + cell_padding) + cell_padding,
            )
            y = (top_left['y'], top_left['y'] + size)
            x = (top_left['x'], top_left['x'] + size)

            hex_color = get_class_color(labels[i][j])
            color_block = make_textured_color_block(
                size=size,
                base_color=hex_to_cv2_color(hex_color),
            )
            viz_img[y[0]:y[1], x[0]:x[1]] = color_block

    return viz_img
    # # -----------------------------------------------------------
    # NOTE: For the "easy method", we don't need this.
    #   If we attempt the hard method again, we may want it back.
    # s = LABEL_VIZ.scale_factor
    # scaled_size = (int(VIZ_IMG_SIZE.width * s), int(VIZ_IMG_SIZE.height * s))
    # return cv2.resize(viz_img, scaled_size)

def normalize_label_file_content(content):
    def keep_line(line):
        line = line.strip()
        # drop blank lines
        if not line:
            return False
        # drop comments
        return line[0] != '#' if line else False

    def normalize_line(line):
        # Separate every char by a single space
        return ' '.join(line.strip().replace(' ', ''))

    raw_lines = content.strip().split('\n')
    cleaned_lines = [normalize_line(line) for line in raw_lines]
    cleaned_content = '\n'.join(
        line for line in cleaned_lines if keep_line(line)
    )
    return cleaned_content

def normalize_label_file(label_path):
    with open(label_path, 'r') as f:
        content = f.read()
    with open(label_path, 'w') as file:
        file.write(normalize_label_file_content(content))

def get_label_filename(image_filename):
    return os.path.splitext(image_filename)[0] + '.txt'

def images_in_dir(dirpath):
    return [f for f in os.listdir(dirpath) if is_image(f)]

def is_label_valid(label_path):
    normalize_label_file(label_path)
    return validate_labels(label_path)

def label_images(data_dir):
    image_dir = os.path.join(data_dir, 'images')
    label_dir = os.path.join(data_dir, 'labels')
    assert os.path.exists(image_dir), f'Image dir does not exist: {image_dir}'
    assert os.path.exists(label_dir), f'Label dir does not exist: {label_dir}'

    image_files = images_in_dir(image_dir)

    total_images_count = len(image_files)
    labeled_images_count = len([
        True for f in image_files if validate_labels(
            os.path.join(label_dir, get_label_filename(f))
        )
    ])

    labeled_in_this_session = 0
    labels_to_go = total_images_count - labeled_images_count

    print('## Annotation Tool ##')
    print('---------------------')
    print('Total images:', total_images_count)
    print('Labeled:', labeled_images_count)
    print('Unlabled:', labels_to_go)
    print('---------------------')

    for i, image_filename in enumerate(image_files):
        label_filename = get_label_filename (image_filename)
        label_path = os.path.join(label_dir, label_filename)

        if os.path.exists(label_path):
            normalize_label_file(label_path)
            if validate_labels(label_path):
                print('Skipping... Valid existing labels found:', label_filename)
                continue

        img_path = os.path.join(image_dir, image_filename)

        # Load and resize the image, then display it
        img = cv2.imread(img_path)
        img = cv2.resize(img, (VIZ_IMG_SIZE.width, VIZ_IMG_SIZE.height))

        window_name = f'Image to Label (completed so far: {labeled_in_this_session}/{labels_to_go})'
        cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
        cv2.imshow(window_name, img)
        cv2.waitKey(1)

        while True:
            subprocess.call(['vim', label_path])
            normalize_label_file(label_path)

            if not validate_labels(label_path):
                with open(label_path, 'r+') as f:
                    content = f.read()
                    f.seek(0, 0)
                    counts = get_class_counts(content)
                    invalid_classes = [name for name, count in counts.items() if count != 5]
                    error_msg = '\n'.join([
                        '# ERROR: Invalid label file!',
                        '# It should have exactly 5 occurrences of each class.',
                        f'# {", ".join(invalid_classes)} need to be fixed.',
                        '# Please correct the labels.',
                        '# --------------------------',
                    ])
                    f.write(error_msg + '\n' + content)
                continue

            label_viz_img = visualize_labels(label_path)
            cv2.destroyAllWindows()
            combined_img = np.hstack((img, label_viz_img))

            num_left = labels_to_go - (labeled_in_this_session+1)
            window_name = f'Verification ({num_left} to go!)'
            cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
            cv2.imshow(window_name, combined_img)
            cv2.waitKey(1)

            user_input = input(' '.join([
                'If visual verification is correct, press ENTER.',
                'If not, press any other key to edit labels: ',
            ]))
            # This means the label was valid
            if user_input == '':
                labeled_in_this_session += 1
                break

        cv2.destroyAllWindows()
        print('Saved labels for ' + image_filename)

    print('Finished labeling all images')

if __name__ == '__main__':
    if len(sys.argv) != 2:
        print('Usage: python annotation_tool_v2.py <data_dir>')
        sys.exit(1)

    data_dir = sys.argv[1]
    print('data_dir:', data_dir)
    label_images(data_dir)


from aesara.compile import optdb
from aesara.graph.rewriting.basic import WalkingGraphRewriter, node_rewriter
from aesara.typed_list.basic import Append, Extend, Insert, Remove, Reverse

@node_rewriter([Append, Extend, Insert, Reverse, Remove], inplace=True)
def typed_list_inplace_rewrite(fgraph, node):
    if (
        isinstance(node.op, (Append, Extend, Insert, Reverse, Remove))
        and not node.op.inplace
    ):
        new_op = node.op.__class__(inplace=True)
        new_node = new_op(*node.inputs)
        return [new_node]
    return False

optdb.register(
    "typed_list_inplace_rewrite",
    WalkingGraphRewriter(
        typed_list_inplace_rewrite, failure_callback=WalkingGraphRewriter.warn_inplace
    ),
    "fast_run",
    "inplace",
    position=60,
)


import numpy as np
import cv2
import tensorflow as tf

# Cargar el modelo de TensorFlow
print("[INFO] Cargando el modelo...")
PATH_TO_CKPT = "TiempoReal/faster_rcnn_inception_v2_coco_2018_01_28/frozen_inference_graph.pb"

detection_graph = tf.Graph()
with detection_graph.as_default():
    od_graph_def = tf.compat.v1.GraphDef()
    with tf.compat.v1.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
        serialized_graph = fid.read()
        od_graph_def.ParseFromString(serialized_graph)
        tf.compat.v1.import_graph_def(od_graph_def, name='')
    sess = tf.compat.v1.Session(graph=detection_graph)

# Definir tensores de entrada y salida
image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
detection_boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
detection_scores = detection_graph.get_tensor_by_name('detection_scores:0')
detection_classes = detection_graph.get_tensor_by_name('detection_classes:0')
num_detections = detection_graph.get_tensor_by_name('num_detections:0')

# Hash de colores para las clases detectadas
colors_hash = {}

# Abrir archivo de texto para guardar los resultados de las detecciones
detections_file = open("detections.txt", "w")

# Leer imagen
image_path = 'Imagenes/frame_00002.png'
color_image = cv2.imread(image_path)

# Realizar la detección usando el modelo
image_expanded = np.expand_dims(color_image, axis=0)
(boxes, scores, classes, num) = sess.run(
    [detection_boxes, detection_scores, detection_classes, num_detections],
    feed_dict={image_tensor: image_expanded})

boxes = np.squeeze(boxes)
classes = np.squeeze(classes).astype(np.int32)
scores = np.squeeze(scores)

# Almacenar resultados si hay detecciones con un score mayor al umbral
for idx in range(int(num)):
    if scores[idx] > 0.6:
        class_ = classes[idx]
        score = scores[idx]
        box = boxes[idx]

        # Escribir en el archivo de texto
        detections_file.write(f"Class: {class_}, Score: {score}, Box: {box}\n")

# Mostrar la imagen
cv2.namedWindow('Result', cv2.WINDOW_AUTOSIZE)
cv2.imshow('Result', color_image)
cv2.waitKey(0)

# Cerrar el archivo de texto y la sesión de TensorFlow
detections_file.close()
sess.close()
cv2.destroyAllWindows()


import logging
from datetime import datetime
from django.conf import settings
from django.contrib.auth.models import User
from pylti1p3.grade import Grade
from pylti1p3.contrib.django import DjangoMessageLaunch, DjangoCacheDataStorage, DjangoDbToolConf
from pylti1p3.lineitem import LineItem
from pylti1p3.exception import LtiServiceException

logger = logging.getLogger('aplus.lti_tool')

def get_launch_url(request):
    target_link_uri = request.POST.get('target_link_uri', request.GET.get('target_link_uri'))
    if not target_link_uri:
        logger.error('Missing "target_link_uri" param')
        raise Exception('Missing "target_link_uri" param')
    return target_link_uri

def get_tool_conf():
    # Cannot default to DjangoDbToolConf() in settings.py due to models not being initialized yet
    if hasattr(settings, "LTI_TOOL_CONF"):
        return settings.LTI_TOOL_CONF
    else:
        return DjangoDbToolConf()

def get_launch_data_storage():
    return DjangoCacheDataStorage()

def send_lti_points(request, submission):
    from exercise.exercise_summary import UserExerciseSummary
    exercise = submission.exercise
    request.COOKIES['lti1p3-session-id'] = submission.meta_data.get('lti-session-id')
    launch = DjangoMessageLaunch.from_cache(
        submission.lti_launch_id,
        request,
        get_tool_conf(),
        launch_data_storage=get_launch_data_storage()
    )

    try:
        username = launch.get_launch_data()['https://purl.imsglobal.org/spec/lti/claim/ext']['user_username']
    except (KeyError, TypeError):
        username = launch.get_launch_data()['email']

    try:
        user = User.objects.get(username=username)
    except User.DoesNotExist:
        logger.warn(f"Tried to send LTI points for a non-existing user '{username}'")
        return

    # Moodle does not have gradebook entries for teachers - don't send result if submitter is a teacher
    is_course_teacher = exercise.course_instance.is_teacher(user)
    if not is_course_teacher:
        summary = UserExerciseSummary(exercise, user)
        best_submission = summary.best_submission
        ags = launch.get_ags()
        grade = Grade()
        (grade.set_score_given(best_submission.grade)
            .set_timestamp(best_submission.submission_time.strftime('%Y-%m-%dT%H:%M:%S+0000'))
            .set_score_maximum(exercise.max_points)
            .set_activity_progress('Completed')
            .set_grading_progress('FullyGraded')
            .set_user_id(launch.get_launch_data().get('sub')))
        line_item = LineItem()
        line_item.set_tag(str(submission.exercise.id))
        try:
            ags.put_grade(grade, line_item)
        except LtiServiceException as e:
            # At least Moodle sends a 409 when trying to save
            # a grade with same timestamp as an existing grade
            if e.response.status_code == 409:
                logger.info("Grade for submission has already been saved through LTI; continuing")
            else:
                raise e


"""remove unused columns

Revision ID: 80a9a5fab858
Revises: 02e1b754c22d
Create Date: 2023-06-11 17:19:02.490808

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '80a9a5fab858'
down_revision = '02e1b754c22d'
branch_labels = ()
depends_on = None

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('game', 'in_progress')
    op.drop_column('player', 'in_room')
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('player', sa.Column('in_room', sa.BOOLEAN(), autoincrement=False, nullable=True))
    op.add_column('game', sa.Column('in_progress', sa.BOOLEAN(), autoincrement=False, nullable=True))
    # ### end Alembic commands ###