from users.models import MossaicUser

from risk_models.models import *
from projects.models import *
from communities.models import *

from django import forms
from django.forms.models import *
from django.forms import ModelForm, Textarea
from django.forms.widgets import HiddenInput
from django.forms.models import inlineformset_factory
from django.forms.models import modelformset_factory
from django.forms.models import BaseInlineFormSet
from django.forms import ModelForm, Textarea
from django.forms.widgets import HiddenInput

# this code is terrible....  will fix someday

class SurveyItem(ModelForm):
	class Meta:
		model = Observation
		widgets = {
			'community': HiddenInput,
			'user': HiddenInput,
			'timestamp': HiddenInput,
			'metric': HiddenInput
		}

	def __init__(self, *args, **kwargs):
		self.request = kwargs.pop('request', None)
		return super(SurveyItem, self).__init__(*args, **kwargs)

	def is_filled(self):
		cleaned_data = self.cleaned_data
		metric = cleaned_data.get("metric")

		if metric.metricType == 'M':
			mcValue = cleaned_data.get("mcValue")
			if mcValue == None:
				return False
			return True

		if metric.metricType == 'D':
			value = cleaned_data.get("value")
			if value == None:
				return False
			return True

		return False

	def clean(self):
		cleaned_data = self.cleaned_data
		metric = cleaned_data.get("metric")

		if metric.metricType == 'M':
			mcValue = cleaned_data.get("mcValue")
			if mcValue == None:
				raise forms.ValidationError('No choice made')
			return cleaned_data

		if metric.metricType == 'D':
			value = cleaned_data.get("value")
			if value == None:
				raise forms.ValidationError('No choice made')
			return cleaned_data

	def save(self, *args, **kwargs):
		kwargs['commit'] = False

		obs = super(SurveyItem, self).save(*args, **kwargs)
		if self.request:
			obs.user = MossaicUser.objects.get(pk=self.request.user.id)  #there must be a better way...

		obs.save()


from pyramid.httpexceptions import HTTPError
from pyramid.httpexceptions import HTTPNotFound
from oekocms.views import error_view
from oekocms.views import exception_decorator
from fanstatic import Library
from fanstatic import Resource
import kotti.static as ks

lib_oekocms = Library('oekocms', 'static')
view_css =  Resource(lib_oekocms, "layout.css", depends=[ks.view_css])
edit_css =  Resource(lib_oekocms, "edit.css", depends=[ks.edit_css])
nav_css =  Resource(lib_oekocms, "primary-navigation.css")

def add_fanstatic_resources(config):
    ks.view_needed.add(view_css)
    ks.view_needed.add(nav_css)
    ks.edit_needed.add(edit_css)

def includeme(config):
    config.include('pyramid_zcml')
    config.load_zcml('configure.zcml')
    config.add_view(
        error_view,
        context=HTTPNotFound,
        renderer='oekocms:templates/view/error-404.pt',
    )
    config.add_view(
        error_view,
        context=HTTPError,
        renderer='oekocms:templates/view/error.pt',
    )
    config.add_view(
        error_view,
        decorator=exception_decorator,
        context=Exception,
        renderer='oekocms:templates/view/error.pt',
    )
    config.add_static_view('static-oekocms', 'oekocms:static')
    config.override_asset('kotti', 'oekocms:kotti-overrides/')
    add_fanstatic_resources(config)


import sys
from collections import deque
dq = deque()
N, K = map(int, sys.stdin.readline().rstrip().split(' '))

for i in range(1, N + 1):
    dq.append(i)
eleminated = []
while len(dq) != 0:
    count = 1
    while count < K:
        dq.append(dq.popleft())
        count += 1

    eleminated.append(dq.popleft())

print('<', end='')
for e in range(len(eleminated)):
    print(eleminated[e], end='')
    if e < len(eleminated) - 1: print(',',end=' ')

print('>')


import streamlit as st
import pandas as pd
import matplotlib.pyplot as plt
import pickle
from joblib import dump, load
from sklearn import ensemble
from sklearn import metrics
import numpy as np

def main():
  GrBosstClass = load_GRB()
  Bagging = load_Bagging()
  data = loadSet()
  defaulData = loadDefaultSet()
  currentModelSelected = 0
  vl15H = 0
  speedWind = 0
  cloydy3H = 0
  vl9H = 0
  rainToday = 1
  sun = 0
  tempAir15H = 0
  dav15H = 0
  minTemp = 0
  maxTemp = 0

  st.title("Модуль С")
  st.markdown("", unsafe_allow_html=True)
  st.sidebar.markdown('
 Модели
', unsafe_allow_html=True)
  modelSelect = st.sidebar.radio("Выберите модель машинного обучения", ["Градиентный бустинг", "Бэггиннг"])

  st.sidebar.markdown('
 Дата сеты
', unsafe_allow_html=True)
  dataSetSelect = st.sidebar.radio("Выберите дата сет", ["Исходный", "После препроцесса"])

  if dataSetSelect == "После препроцесса":
    '''В датасете после препроцесса остались только самые важные десять полей. Также перекодированы столбцы: локация, направление ветра и был ли сегодня дождь.'''
    st.write(data.head(10))

  if dataSetSelect == "Исходный":
    ''' Исходный датасет имеет полный список полей. Также в нём не заполнены пустые значения и ни один признак не перекодирован.'''
    st.write(defaulData.head(10))

  if modelSelect == "Градиентный бустинг":
    currentModelSelected = GrBosstClass
    "Предсказание градиентного бустинга"
    "Градиентный бустинг предсказывает с точностью в 85%"

  if modelSelect == "Бэггиннг":
    currentModelSelected = Bagging
    "Предсказание бэггиннга"
    "Бэггинг предсказывает с точностью в 84%"
  "Для предсказания дождя на завтрашний день исопльзуются основные 10 параметров."
  ""
  inpType = st.radio("Как будете вводить данные?", ['Строкой', "Буду заполнять каждое поле отдельно!"])
  if inpType == "Буду заполнять каждое поле отдельно!":
    vl15H = st.number_input("Влажность воздуха в 15:00")
    speedWind = st.number_input("Скорость порыва ветра")
    cloydy3H = st.number_input("Облачность в 15:00 (от 0 до 9)")
    vl9H = st.number_input("Влажность в 9 утра")
    rainTodayStr = st.radio("Был ли сегодня дождь?", ["Да" , "Нет"])
    rainToday = 1
    if rainTodayStr =="Да":
      rainToday = 1
    else:
      rainToday = 0
    sun = st.number_input("Солнечный свет (от 0 до 13,9)")
    tempAir15H = st.number_input("Температура воздуха в 15:00")
    dav15H = st.number_input("Давление в 15:00")
    minTemp = st.number_input("Минимальная температура воздуха")
    maxTemp = st.number_input("Максимальная температура воздуха")
  if inpType == "Строкой":
    a = st.text_input('Ввести данные строкой:', help= "Ввдетие числа через запятую. Без точек и запятых в конце строки!")
    if a:
      a = a.split(',')
      a = [float(i) for i in a]
      polya = a
  else:
    polya = int(currentModelSelected.predict([[vl15H,speedWind,cloydy3H,vl9H,rainToday,sun,tempAir15H,dav15H,minTemp,maxTemp]]))
  "Введенные данные: " + str(vl15H) + ", " + str(speedWind) + ", " + str(cloydy3H) + ", " + str(vl9H) + ", " +str(rainToday) + ", " + str(sun) + ", " + str(tempAir15H) + ", " + str(dav15H) + ", " + str(minTemp) + ", " + str(maxTemp) + "."
  if st.button("Рассчитать прогноз", key=None, help="Предсказать будет ли дождь завтра при помощи метода " + modelSelect):
    res = polya
    if res == 0:
      st.markdown("
Скорее всего завтра не будет дождя 😄
", unsafe_allow_html=True)
    else:
      st.markdown("
Скорее всего завтра будет дождь... 😔
", unsafe_allow_html=True)

@st.cache
def loadSet():
  df = pd.read_csv("data/watherPreProcces.csv")
  return df

### models

@st.cache
def load_GRB():
  with open('models/GrBosstClass.pkl', 'rb') as pkl_file:
    grb = pickle.load(pkl_file)
  return grb

@st.cache(allow_output_mutation=True)
def load_Bagging():
  with open('models/Bagging.pkl', 'rb') as pkl_file:
    Bagging = pickle.load(pkl_file)
  return Bagging

@st.cache
def loadDefaultSet():
  df = pd.read_csv("data/weather.csv")
  return df

if __name__ == "__main__":
  main()


import setuptools

with open("README.md", "r") as fh:
    long_description = fh.read()

setuptools.setup(
    name="outlierpack-NG",
    version="0.1.0",
    author="Nikhil Gupta",
    author_email="ngupta_be17@thapar.edu",
    description="Removing outliers from a pandas dataframe",
	url='https://github.com/CachingNik/OutlierPack',
	long_description=long_description,
	long_description_content_type="text/markdown",
	packages=setuptools.find_packages(),
	entry_points = {
        'console_scripts': ['Outcli=outlib.outcli:main'],
    },
	keywords = ['CLI', 'OUTLIER', 'Data', 'outlier removal'],
	python_requires='>=2.7',
)


import requests
import threading
import sys
import os
from bs4 import BeautifulSoup
from pandas import DataFrame
from functools import reduce

if len(sys.argv) == 1:
    CSV_FNAME = 'volunteermatch_data.csv'
else:
    CSV_FNAME = sys.argv[1]

URL_PART1 = 'https://www.volunteermatch.org/search/'

locations = ['New+York%2C+NY%2C+USA', 'Chicago%2C+IL%2C+USA',
             'San+Francisco%2C+CA%2C+USA', 'Boston%2C+MA%2C+USA',
             'Houston%2C+TX%2C+USA', 'Los+Angeles%2C+CA%2C+USA',
             'Philadelphia%2C+PA%2C+USA', 'Seattle%2C+WA%2C+USA',
             'Atlanta%2C+GA%2C+USA', 'Dallas%2C+TX%2C+USA',
             'Portland%2C+OR%2C+USA', 'Cleveland%2C+OH%2C+USA',
             'Denver%2C+CO%2C+USA', 'Washington%2C+DC%2C+USA']

categories = {
    'community': 25,
    'arts_culture': 34,
    'advocacy': 23,
    'seniors': 12,
    'homeless_housing': 7,
    'health_med': 11,
    'child_youth': 22,
    'animals': 30,
    'edu_lit': 15,
    'crisis_support': 14,
    'women': 3
}

dfs = []

def url_to_df(urls, cat):
    opps = []
    for url in urls:
        r = requests.get(url)
        soup = BeautifulSoup(r.content, 'html5lib')
        table = soup.find('div', attrs={'class': 'search-page'})
        for row in table.findAll('div', attrs={'class': 'searchitem PUBLIC'}):
            opp = {}
            opp['title'] = row.h3.text.strip()
            opp['org'] = row.find_all('a')[1].text.strip()
            desc_search = row.find_all('p')
            desc_index = 0
            for i in range(len(desc_search)):
                if len(desc_search[i].getText()) > 100:
                    desc_index = i
            opp['desc'] = row.find_all('p')[desc_index].getText().strip()
            opp['desc'] = opp['desc'].split('\n')[0]
            opp[cat] = True
            opps.append(opp)
    df = DataFrame(opps)
    df = df.drop_duplicates(keep=False)
    dfs.append(df)

threads = []
for cat, cat_v in categories.items():
    urls = []
    for loc in locations:
        url = URL_PART1 + f'?categories={cat_v}&' \
                        + f'l={loc}'
        urls += [url + f'&s={s}' for s in [x*10+1 for x in range(100)]]
    t = threading.Thread(target=url_to_df, args=(urls, cat))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

final_df = reduce(lambda df1, df2: df1.merge(df2, left_on=['title', 'org', 'desc'],
                                                  right_on=['title', 'org', 'desc'],
                                                  how='outer'), dfs)
final_df = final_df.fillna(False)
final_df.to_csv(CSV_FNAME)


"""
wordcloud.py: A reusable library for word cloud visualizations
"""

"""
from PIL import Image
from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
import pandas as pd

def make_wordcloud(results, vid_dict):
    cloud = WordCloud(background_color="white",width=1000,height=1000, max_words=10,relative_scaling=0.5,
                    normalize_plurals=False).generate_from_frequencies(results[vid_dict])

    plt.imshow(cloud)
"""
import matplotlib.pyplot as plt
from wordcloud import WordCloud

word_could_dict = {'Git':100, 'GitHub':100, 'push':50, 'pull':10, 'commit':80, 'add':30, 'diff':10,
                  'mv':5, 'log':8, 'branch':30, 'checkout':25}

print(word_could_dict['Git'])

wordcloud = WordCloud(width = 1000, height = 500).generate_from_frequencies(word_could_dict)

plt.figure(figsize=(15,8))
plt.imshow(wordcloud)
plt.show()


"""URL patterns for Directory Services"""
from django.urls import path

# Must be full path import to allow including url patterns in project urls
from os2datascanner.projects.admin.import_services import views

urlpatterns = [
     path('ldap/add/<uuid:org_id>',
          views.LDAPAddView.as_view(),
          name='add-ldap'),
     path('ldap/edit/<uuid:pk>',
          views.LDAPUpdateView.as_view(),
          name='edit-ldap'),
     path('ldap/test/connection',
          views.verify_connection,
          name='test-ldap-connection'),
     path('ldap/test/authentication',
          views.verify_authentication,
          name='test-ldap-authentication'),
     path('ldap/import/<uuid:pk>',
          views.LDAPImportView.as_view(),
          name='import-ldap'),
     path('msgraph-organization/add/<uuid:org_id>',
          views.MSGraphAddView.as_view(),
          name='add-msgraph'),
     path('msgraph-organization/add/<uuid:org_id>/',
          views.MSGraphAddView.as_view(),
          name='add-msgraph'),
     path('msgraph-organization/edit/<uuid:pk>',
          views.MSGraphUpdateView.as_view(),
          name='edit-msgraph'),
     path('msgraph-organization/import/<uuid:pk>',
          views.MSGraphImportView.as_view(),
          name='import-msgraph'),
     path('os2mo-organization/add/<uuid:org_id>',
          views.OS2moAddView.as_view(),
          name='add-os2mo'),
     path('os2mo-organization/import/<uuid:pk>',
          views.OS2moImportView.as_view(),
          name='import-os2mo'),
]


import wx
from wx.lib.agw import customtreectrl
from wx.lib.agw.aui import GetManager

from ..controller.project import Project
from ..pluginapi import Plugin
from ..pluginapi.plugin import ActionInfo

class FileExplorerPlugin(Plugin):
    """Provides a tree view for Files and Folders. Opens selected item with mouse right-click."""
    datafile = property(lambda self: self.get_selected_datafile())
    defaults = {"opened": True,
                "docked": True,
                "own colors": False
                }

    def __init__(self, application, controller=None):
        Plugin.__init__(self, application, default_settings=self.defaults)
        self._app = application
        self.settings = self._app.settings.config_obj['Plugins']['File Explorer']
        self._parent = wx.App.Get().GetTopWindow()
        self._filemgr = self.filemgr
        self._filemgr.SetThemeEnabled(True)
        self._mgr = GetManager(self._filemgr)
        self._controller = controller
        self._pane = None
        self._filetreectrl = None
        self.font = self._filemgr.GetFont()

    def register_frame(self, parent=None):
        if parent:
            self._parent = parent

            if self._mgr.GetPane("file_manager") in self._mgr._panes:
                register = self._mgr.InsertPane
            else:
                register = self._mgr.AddPane

            register(self._filemgr, wx.lib.agw.aui.AuiPaneInfo().Name("file_manager").
                     Caption("Files").LeftDockable(True).CloseButton(True))

            self._mgr.Update()

    def enable(self):
        self.register_action(ActionInfo('View', 'View File Explorer', self.on_show_file_explorer,
                                        shortcut='F11',
                                        doc='Show File Explorer panel',
                                        position=1))
        # self.save_setting('opened', True)
        if self.opened:
            self.on_show_file_explorer(None)

    def close_tree(self):
        self._mgr.DetachPane(self._filemgr)
        self._filemgr.Hide()
        self._mgr.Update()
        self.save_setting('opened', False)

    def disable(self):
        self.close_tree()
        # self.save_setting('opened', False)
        self.unsubscribe_all()
        self.unregister_actions()

    def is_focused(self):
        return self._filemgr.HasFocus()

    def on_show_file_explorer(self, event):
        _ = event
        if not self._parent:
            self._parent = wx.App.Get().GetWindow()  # self.frame
        if not self._filemgr:  # This is not needed because file explorer is always created
            self._filemgr = FileExplorer(self._parent, self._controller)

        self._pane = self._mgr.GetPane(self._filemgr)
        global_settings = self._app.settings.config_obj['General']
        apply_global = global_settings['apply to panels']
        use_own = self.settings['own colors']
        if apply_global or not use_own:
            html_background = self.settings.get('background help', (240, 242, 80))
            html_foreground = self.settings.get('foreground text', (7, 0, 70))
        else:
            html_background = self.settings.get('background', (240, 242, 80))
            html_foreground = self.settings.get('foreground', (7, 0, 70))
        html_font_face = self.settings.get('font face', '')
        html_font_size = self.settings.get('font size', 11)
        self._filetreectrl = self._filemgr.GetTreeCtrl()
        self._filemgr.Show(True)
        self._filemgr.SetMinSize(wx.Size(200, 225))
        self._mgr.DetachPane(self._filemgr)
        self._mgr.AddPane(self.filemgr,
                          wx.lib.agw.aui.AuiPaneInfo().Name("file_manager").
                          Caption("Files").LeftDockable(True).
                          CloseButton(True))
        self._filemgr.SetBackgroundStyle(wx.BG_STYLE_SYSTEM)
        self._filemgr.SetBackgroundColour(html_background)
        self._filemgr.SetForegroundColour(html_foreground)
        self.font = self._filemgr.GetFont()
        self.font.SetFaceName(html_font_face)
        self.font.SetPointSize(html_font_size)
        self._filemgr.SetFont(self.font)
        self._filemgr.Refresh()
        self._filetreectrl.SetBackgroundColour(html_background)
        self._filetreectrl.SetForegroundColour(html_foreground)
        self._filetreectrl.SetFont(self.font)
        self._filetreectrl.Refresh()
        self._filemgr.Raise()
        self._mgr.Update()
        self.save_setting('opened', True)
        self.update_tree()

    def update_tree(self):
        if not self._filemgr:
            return
        self._filemgr.update_tree()

class FileExplorer(wx.GenericDirCtrl):

    def __init__(self, parent, controller=None):
        wx.GenericDirCtrl.__init__(self, parent, id=-1, size=(200, 225), style=wx.DIRCTRL_3D_INTERNAL)
        self._controller = controller
        self.SetThemeEnabled(True)
        self.Refresh()

    def update_tree(self):
        if isinstance(self._controller, Project):
            if self._controller.data and len(self._controller.data.directory) > 1:
                self.SelectPath(self._controller.data.source)
                try:
                    self.ExpandPath(self._controller.data.source)
                except Exception:
                    pass
                self.Refresh()
                self.Update()


#coding=utf-8
import sys
import pygame
from Bullet import Bullet
from Alien import Alien
from time import sleep

def check_keydown_events(event,ai_settings,screen,ship,bullets,stats,play_Button,aliens,sb):
    """按键响应"""
     #按下的是方向键右
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
     #按下的是方向键左
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True
    #按下的是空格
    elif event.key == pygame.K_SPACE:
        fire_bullet(ai_settings,screen,ship,bullets)
     #按下q
    elif event.key == pygame.K_q:
        sys.exit()#退出游戏
        #按下p
    elif event.key == pygame.K_p:
        start_game(ai_settings,screen,stats,play_Button,ship,aliens,bullets,sb)

def check_play_button(ai_settings,screen,stats,play_Button,ship,aliens,bullets,sb,mouse_x,mouse_y):
    """鼠标点击play按钮时的相应"""
    if play_Button.rect.collidepoint(mouse_x,mouse_y) and not stats.game_action:
       start_game(ai_settings,screen,stats,play_Button,ship,aliens,bullets,sb)

def start_game(ai_settings,screen,stats,play_Button,ship,aliens,bullets,sb):
    """开始游戏"""
     #改变游戏是否开开始的标识为true
    stats.game_action = True
    #重置游戏
    stats.reset_stats()
    #清空外星人和子弹
    aliens.empty()
    bullets.empty()
    #创建一组外星人
    create_fleet(ai_settings,screen,ship,aliens)
    #创建飞船
    ship.center_ship()
    #隐藏光标
    pygame.mouse.set_visible(False)
    #重置速度
    ai_settings.initialize_dynamic_settings()
    #重新设置计分
    sb.prep_level()
    sb.prep_score()
    sb.prep_high_score()
    sb.prep_ship()#显示剩余飞机数量

def fire_bullet(ai_settings,screen,ship,bullets):
    """发射子弹"""
    if len(bullets) < ai_settings.bullet_allowed:#如果子弹数量没有超过限制
        new_bullet = Bullet(ai_settings,screen,ship)#创建一个新子弹
        bullets.add(new_bullet)#添加到
def check_keyup_events(event,ship):
    """按键松开"""
    if event.key == pygame.K_RIGHT:
        ship.moving_right = False
    elif event.key == pygame.K_LEFT:
        ship.moving_left = False

def check_events(ai_settings,aliens,screen,ship,bullets,stats,play_Button,sb):
    """按键响应事件"""
    for event in pygame.event.get():
        if event.type == pygame.QUIT:#点击窗口关闭按钮
            sys.exit()#退出游戏
             #检测键盘有按键按下
        elif event.type == pygame.KEYDOWN:
            check_keydown_events(event,ai_settings,screen,ship,bullets,stats,play_Button,aliens,sb)
            #检测键盘是否有按键松开
        elif event.type == pygame.KEYUP:
            check_keyup_events(event,ship)
            #检测是否有鼠标按下
        elif event.type == pygame.MOUSEBUTTONDOWN:
            #获取鼠标点击的位置
            mouse_x,mouse_y = pygame.mouse.get_pos()
            check_play_button(ai_settings,screen,stats,play_Button,ship,aliens,bullets,sb,mouse_x,mouse_y)

def update_screen(ai_settings,screen,ship,stats,aliens,bullets,play_Button,sb):
    """更新动画"""

    screen.fill(ai_settings.screen_color)#为屏幕填充颜色,RGB

    #根据子弹的大小位置等信息绘制子弹
    for bullet in bullets:
        bullet.draw_bullet()
    #绘制飞船
    ship.blitem()
    #自动根据编组内每个成员的rect绘制
    aliens.draw(screen)
    if not stats.game_action:
        play_Button.draw_button()
        #刷新分数
    sb.show_score()
    #让最近绘制的屏幕可见
    pygame.display.flip()#不断擦去旧屏幕，显示新屏幕，不断刷新，形成动画
def update_bullet(ai_settings,screen,ship,stats,aliens,bullets,sb):
    """刷新子弹"""
     #自动对编组中的每一个成员执行update
    bullets.update()

    #对消失的子弹进行删除
    for bullet in bullets:
        if bullet.rect.bottom <= 0:
            bullets.remove(bullet)

    check_bullet_alien_collisions(ai_settings,screen,ship,stats,aliens,bullets,sb)

def check_bullet_alien_collisions(ai_settings,screen,ship,stats,aliens,bullets,sb):
    """外星人与子弹发生碰撞"""
     #检查外星人与子弹是否产生碰撞
    collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)#后面两个布尔值的意思是若发生碰撞则两个元素都删除，
    #若改为false，true则发生碰撞时子弹不消失，外星人消失
    if collisions:
        for aliens in collisions.values():
            stats.score+=ai_settings.alien_points * len(aliens)
            sb.prep_score()
            check_high_score(stats,sb)

    if len(aliens) == 0:#如果外星人全部消失则重新创建一组外星人
        bullets.empty()#清除子弹
        ai_settings.increase_speed()
        create_fleet(ai_settings,screen,ship,aliens)
        stats.level+=1#消灭一组外星人 等级加一
        sb.prep_level()#刷新等级
        ai_settings.bullet_with+=0.5
def update_aliens(ai_settings,stats,screen,ship,aliens,bullets,sb):
    """更新外星人"""
    check_fleet_edges(ai_settings,aliens)
    aliens.update()

    #如果外星人与飞船相撞
    if pygame.sprite.spritecollideany(ship,aliens):
        ship_hit(ai_settings,stats,screen,ship,aliens,bullets,sb)
    #到屏幕底端
    check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets,sb)

def ship_hit(ai_settings,stats,screen,ship,aliens,bullets,sb):
    """外星人与飞船相撞"""

    if stats.ships_left > 1:
        stats.ships_left-=1#飞船数减一
        aliens.empty()#外星人重置
        bullets.empty()#子弹重置
        create_fleet(ai_settings,screen,ship,aliens)#创建新的外星人
        ship.center_ship()#重置飞船位置
        stats.game_action = True
        sleep(0.1)#暂停0.1s
        sb.prep_ship()#更新当前飞机图标
    else :
        stats.game_action = False
        pygame.mouse.set_visible(True)

def get_number_aliens_x(ai_settings,alien_width):
    """计算每行外星人数"""
    available_space_x = ai_settings.screen_width - (3 * alien_width)#减去一个外星人的位置
    number_aliens_x = int(available_space_x / (2 * alien_width))#能放多少个外星人
    return number_aliens_x

def create_alien(ai_settings,screen,aliens,alien_number,number_row):
    """创建一个外星人，并将它放到分组里"""
    alien = Alien(ai_settings,screen)#创建一个外星人
    alien_width = alien.rect.width
    alien.x = alien_width + 2 * alien_width * alien_number#位置，每个外星人之间间隔一个外星人的距离
    alien.rect.x = alien.x#设置位置，外星人的位置由rect中的值决定
    alien.rect.y =3* alien.rect.height + 2 * alien.rect.height * number_row
    aliens.add(alien)#添加到编组中
def get_number_rows(ai_settings,ship_height,alien_height):
    """计算可容纳多少行外星人"""
    available_space_y = ai_settings.screen_height - 4* alien_height - ship_height
    #窗口高度减去外星人与最上面边距之间的距离，外星人与飞船之间的距离（外星人高度的三倍），飞船的高度
    number_rows = available_space_y / (2 * alien_height)#减后的距离除以外星人所占的高度（每行外星人之间有一行外星人高度的距离）
    return number_rows

def create_fleet(ai_settings,screen,ship,aliens):
    """创建一组外星人"""
    alien = Alien(ai_settings,screen)#生成外星人单个实例
    alien_width = alien.rect.width#外星人宽
    number_aliens_x = get_number_aliens_x(ai_settings,alien_width)#一行创建多少个外星人
    number_rows = int(get_number_rows(ai_settings,ship.rect.height,alien.rect.height))#创建多少行外星人

    for number_row in range(number_rows):
        for alien_number in range(number_aliens_x):#从0开始计数
            create_alien(ai_settings,screen,aliens,alien_number,number_row)#创建外星人
def check_fleet_edges(ai_settings,aliens):
    """外星人到达屏幕边缘做出的反应"""
    for alien in aliens.sprites():
        if alien.check_edges():
            change_fleet_direction(ai_settings,aliens)
            break

def change_fleet_direction(ai_settings,aliens):
    """外星人向下移动，并改变移动方向"""
    for alien in aliens.sprites():
        alien.rect.y+=ai_settings.fleet_drop_speed#向下移动
    ai_settings.fleet_direction *= -1#改变方向
def check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets,sb):
    """检查是否有外星人到达屏幕底端"""
    screen_rect = screen.get_rect()#获取屏幕rect对象
    for alien in aliens.sprites():
        if alien.rect.bottom >= screen_rect.bottom:#当外星人的底部大于或等于窗口的底部时，说明外星人撞到屏幕底部
            ship_hit(ai_settings,stats,screen,ship,aliens,bullets,sb)
            break

def check_high_score(stats,sb):
    """检查分数，获取最高分"""
    if stats.score > stats.high_score:
        stats.high_score = stats.score
        sb.prep_high_score()


# -*- coding: utf-8 -*-
# @Time : 2020/11/22 8:50
# @Author : Zhongyi Hua
# @FileName: ssr_utils.py
# @Usage:
# @Note:
# @E-mail: njbxhzy@hotmail.com

from Bio import SeqIO
from os import remove as del_file
import multiprocessing as multi
from tqdm import tqdm

def build_rep_set(repeat_file, unit_cutoff=None, motif_length_cutoff=None):
    """
        Outputs the repeats info dictionary used by the get_ssrs function.
        Takes list of repeat motifs from repeats file(output by generate_repeats function) as input.
        Creates a dictionary with expanded repeat as the key and (class, motif_length, strand) as values.
        Works either by "length_cutoff=" or by "unit_cutoff=" arguments.
    """
    repeats_out = dict()
    cutoffs = set()
    if unit_cutoff is None:
        unit_cutoff = {1: 9, 2: 6, 3: 6, 4: 6, 5: 5, 6: 4}
    for line in repeat_file:
        motif_dict = dict()
        L = line.strip().split('\t')
        motif_length = int(L[2])
        if motif_length < motif_length_cutoff:
            continue
        motif = L[0]
        motif = motif*unit_cutoff[motif_length]
        cutoffs.add(len(motif))
        motif_dict['class'] = L[1]
        motif_dict['motif_length'] = motif_length
        motif_dict['strand'] = L[3]
        repeats_out[motif] = motif_dict
    repeats_out['cutoff'] = sorted(list(cutoffs))

    return repeats_out

def get_ssrs(seq_record, repeats_info, out):
    """Native function that identifies repeats in fasta files."""
    if type(out) == str:
        out_file = open(out, 'w')
    else:
        out_file = out
    length_cutoffs = repeats_info['cutoff']
    input_seq = str(seq_record.seq).upper()
    input_seq_length = len(input_seq)
    for length_cutoff in length_cutoffs:
        fallback = length_cutoff - 1
        sub_start = 0  # substring start
        sub_stop = sub_start + length_cutoff  # substring stop
        while sub_stop <= input_seq_length:
            sub_stop = sub_start + length_cutoff
            sub_seq = input_seq[sub_start:sub_stop]
            if sub_seq in repeats_info:
                match = True
                repeat_data = repeats_info[sub_seq]
                motif_length = repeat_data['motif_length']
                rep_class = repeat_data['class']
                strand = repeat_data['strand']
                offset = length_cutoff % motif_length
                repeat_seq = input_seq[sub_start+offset:sub_start+offset+motif_length]
                i = 0
                while match:
                    j = sub_stop
                    if sub_stop >= input_seq_length:
                        match = False
                        match_length = sub_stop - sub_start
                        num_units = int(match_length/motif_length)
                        print(seq_record.id, sub_start + 1, sub_stop + 1, rep_class, match_length, strand, num_units, sub_seq[:motif_length], seq_record.id + '_' + str(sub_start + 1), sep="\t", file=out_file)
                        sub_start = sub_stop - fallback
                    elif input_seq[j] == repeat_seq[i]:
                        sub_stop += 1
                        i += 1
                        if i >= motif_length:
                            i = 0
                    else:
                        match = False
                        match_length = sub_stop - sub_start
                        num_units = int(match_length/motif_length)
                        print(seq_record.id, sub_start + 1, sub_stop + 1, rep_class, match_length, strand, num_units, sub_seq[:motif_length], seq_record.id + '_' + str(sub_start + 1), sep="\t", file=out_file)
                        sub_start = sub_stop - fallback
            else:
                sub_start += 1
    if type(out) == str:
        out_file.close()

def fasta_ssrs(args, repeats_info):
    """

    :param args:
    :param repeats_info:  return from build_rep_set function
    :return:
    """
    handle = open(args.input, 'r')

    records = [ _ for _ in SeqIO.parse(handle, 'fasta')]
    num_records = len(records)

    file_output = open(args.output, 'w')
    print('\t'.join(['seqid', 'start', 'end', 'class', 'length', 'strand', 'units', 'motif', 'ID']), file=file_output)

    if args.threads > 1:
        i = 0
        pool = multi.Pool(processes=args.threads)
        for record in records:
            out_name = './temp_%s.tsv' % (i)
            i += 1
            pool.apply_async(get_ssrs, (record, repeats_info, out_name,))

        pool.close()
        pool.join()

        # Concat all the output files into one.
        temp_outs = tqdm(range(num_records), total=num_records)

        for o in temp_outs:
            name = './temp_%s.tsv' % (o)
            temp_outs.set_description("Concatenating file: %d " % (o))
            with open(name, 'r') as fh:
                for line in fh:
                    print(line.strip(), file=file_output)
            del_file(name)

    elif args.threads == 1:
        records = tqdm(records, total=num_records)
        for record in records:
            records.set_description("Processing %s" % (record.id))
            get_ssrs(record, repeats_info, file_output)


import math
import random
import pygame
import sys
from pygame.locals import *
from copy import deepcopy

pygame.init()
pygame.mixer.init()
width, height = 640, 480
screen = pygame.display.set_mode((width, height))
player1keys = [False, False, False, False]
player2keys = [False, False, False, False]
player1pos = [0] #Min: 0 Max: 2130
player2pos = [[615, 150, 3]]
ballpos = [300, 300]
ballvel = [-1, 1]
for num in range(0, 6):
    player1pos.append(player1pos[num] + 17)
    player2pos.append([player2pos[num][0], player2pos[num][1] - 17, 3])
UP, LEFT, DOWN, RIGHT = 0, 1, 2, 3
xMAX, yMAX, xMIN, yMIN = 614, 451, 0, 0
posMIN, posMAX = 0, 2130
hasBounced = False

player1 = pygame.image.load("sprites/player1.png")
player2 = pygame.image.load("sprites/player2.png")
ball = pygame.image.load("sprites/ball.png")

running = 1
exitcode = 0
while running:
    screen.fill(0)

    for box in player1pos:
        if(box <= xMAX):
            screen.blit(player1, [box + 1, yMIN + 1])
        elif(box <= xMAX + yMAX):
            screen.blit(player1, [xMAX + 1, box - xMAX + 1])
        elif(box <= xMAX*2 + yMAX):
            screen.blit(player1, [xMAX*2 + yMAX - box + 1, yMAX + 1])
        else:
            screen.blit(player1, [xMIN + 1, xMAX*2 + yMAX*2 - box + 1])
    for box in player2pos:
        if(box[2] == UP):
            if(box[0] > xMAX):
                box[2] = RIGHT
                box[0] = xMAX
            elif(box[0] < xMIN):
                box[2] = LEFT
                box[0] = xMIN
        if(box[2] == LEFT):
            if(box[1] > yMAX):
                box[2] = DOWN
                box[1] = yMAX
            elif(box[1] < yMIN):
                box[2] = UP
                box[1] = yMIN
        if(box[2] == DOWN):
            if(box[0] > xMAX):
                box[2] = RIGHT
                box[0] = xMAX
            elif(box[0] < xMIN):
                box[2] = LEFT
                box[0] = xMIN
        if(box[2] == RIGHT):
            if(box[1] > yMAX):
                box[2] = DOWN
                box[1] = yMAX
            elif(box[1] < yMIN):
                box[2] = UP
                box[1] = yMIN
        screen.blit(player2, [box[0], box[1]])
    screen.blit(ball, ballpos)
    ballpos[0] += ballvel[0]
    ballpos[1] += ballvel[1]
    #if(player1pos[0][2] == 1 and ballpos[0] <= player1pos[0][0] and ballpos[1] <= player1pos[5][1] and ballpos[1] >= player1pos[0][1]):
    #    ballvel[0] *= -1
    #if(player1pos[0][2] == 3 and ballpos[0] >= player1pos[0][0] - 17 and ballpos[1] >= player1pos[5][1] and ballpos[1] <= player1pos[0][1]):
    #    ballvel[0] *= -1
    if(ballpos[0] > xMAX - 8 or ballpos[0] < xMIN - 10):
        if not hasBounced:
            ballvel[0] *= -1
            hasBounced = True
        else:
            hasBounced = False
    if(ballpos[1] > yMAX - 5 or ballpos[1] < yMIN - 10):
        if not hasBounced:
            ballvel[1] *= -1
            hasBounced = True
        else:
            hasBounced = False
    pygame.display.flip()

    for ev in pygame.event.get():
        if ev.type == KEYDOWN:
            if ev.key == K_w:
                player1keys[0] = True
            elif ev.key == K_a:
                player1keys[1] = True
            elif ev.key == K_s:
                player1keys[2] = True
            elif ev.key == K_d:
                player1keys[3] = True
            if ev.key == K_UP:
                player2keys[0] = True
            elif ev.key == K_LEFT:
                player2keys[1] = True
            elif ev.key == K_DOWN:
                player2keys[2] = True
            elif ev.key == K_RIGHT:
                player2keys[3] = True
        if ev.type == KEYUP:
            if ev.key == K_w:
                player1keys[0] = False
            elif ev.key == K_a:
                player1keys[1] = False
            elif ev.key == K_s:
                player1keys[2] = False
            elif ev.key == K_d:
                player1keys[3] = False
            elif ev.key == K_UP:
                player2keys[0] = False
            elif ev.key == K_LEFT:
                player2keys[1] = False
            elif ev.key == K_DOWN:
                player2keys[2] = False
            elif ev.key == K_RIGHT:
                player2keys[3] = False
        if ev.type == pygame.QUIT:
            pygame.quit()
            sys.exit(0)

    #Checks Player #1's Key inputs
    if player1keys[0]:
        if player1pos[6] > xMAX and player1pos[0] <= xMAX + yMAX:
            for num in range(0,7):
                player1pos[num] -= 2
        if player1pos[6] > xMAX*2 + yMAX:
            for num in range(0,7):
                player1pos[num] += 2
                if player1pos[num] > 2130:
                    player1pos[num] -= 2130
    elif player1keys[2]:
        if player1pos[6] > xMAX and player1pos[0] <= xMAX + yMAX:
            for num in range(0,7):
                player1pos[num] += 2
        if player1pos[6] > xMAX*2 + yMAX:
            for num in range(0,7):
                player1pos[num] -= 2
    elif player1keys[1]:
        if player1pos[6] > xMAX + yMAX and player1pos[0] <= xMAX*2 + yMAX:
            for num in range(0,7):
                player1pos[num] += 2
        if player1pos[0] < xMAX or player1pos[0] > 2015:
            for num in range(0,7):
                player1pos[num] -= 2
                if player1pos[num] < 0:
                    player1pos[num] += 2130
    elif player1keys[3]:
        if player1pos[6] > xMAX + yMAX and player1pos[0] <= xMAX*2 + yMAX:
            for num in range(0,7):
                player1pos[num] -= 2
        if player1pos[0] < xMAX or player1pos[0] > 2010:
            for num in range(0,7):
                player1pos[num] += 2

    #Checks Player #2's key inputs
    if player2keys[0]:
        if player2pos[6][2] == LEFT:
            for box in player2pos:
                if(box[2] == LEFT):
                    box[1] -= 2
                elif(box[2] == UP):
                    box[0] += 2
        elif player2pos[0][2] == RIGHT:
            for box in player2pos:
                if(box[2] == RIGHT):
                    box[1] -= 2
                elif(box[2] == UP):
                    box[0] -= 2
    elif player2keys[2]:
        if player2pos[0][2] == LEFT:
            for box in player2pos:
                if(box[2] == LEFT):
                    box[1] += 2
                elif(box[2] == DOWN):
                    box[0] += 2
        elif player2pos[6][2] == RIGHT:
            for box in player2pos:
                if(box[2] == RIGHT):
                    box[1] += 2
                elif(box[2] == DOWN):
                    box[0] -= 2
    elif player2keys[1]:
        if player2pos[0][2] == UP:
            for box in player2pos:
                if(box[2] == UP):
                    box[0] -= 2
                elif(box[2] == LEFT):
                    box[1] += 2
        elif player2pos[6][2] == DOWN:
            for box in player2pos:
                if(box[2] == DOWN):
                    box[0] -= 2
                elif(box[2] == LEFT):
                    box[1] -= 2
    elif player2keys[3]:
        if player2pos[6][2] == UP:
            for box in player2pos:
                if(box[2] == UP):
                    box[0] += 2
                elif(box[2] == RIGHT):
                    box[1] += 2
        elif player2pos[0][2] == DOWN:
            for box in player2pos:
                if(box[2] == DOWN):
                    box[0] += 2
                elif(box[2] == RIGHT):
                    box[1] -= 2
    pygame.time.delay(6)


import os
import re
import csv
import spacy
import convert2txt

nlp = spacy.load('skill-cv-bn')

def create_dic(filename):
    result = {
                'Filename': filename,
                'Name':[],
                'Number':[],
                'Email':[],
                'Experience':[],
                'Companies':[],
                'Designation':[],
                'Responsibilities':[],
                'Skills':[],
                'Certification':[],
                'Degree':[],
                'Institution':[],
                'Edu_subject':[],
                'Graduation_year':[]
                }
    return result

def get_info(text, dic_name):
    nlp_text = nlp(text)
    for e in nlp_text.ents:
        if e.label_ == 'Name':
            dic_name['Name'].append(e.text)
        elif e.label_ == 'Number':
            dic_name['Number'].append(e.text)
        elif e.label_ == 'Email':
            dic_name['Email'].append(e.text)
        elif e.label_ == 'Experience':
            dic_name['Experience'].append(e.text)
        elif e.label_ == 'Companies':
            dic_name['Companies'].append(e.text)
        elif e.label_ == 'Designation':
            dic_name['Designation'].append(e.text)
        elif e.label_ == 'Responsibilities':
            dic_name['Responsibilities'].append(e.text)
        elif e.label_ == 'Skills':
            dic_name['Skills'].append(e.text)
        elif e.label_ == 'Certification':
            dic_name['Certification'].append(e.text)
        elif e.label_ == 'Degree':
            dic_name['Degree'].append(e.text)
        elif e.label_ == 'Institution':
            dic_name['Institution'].append(e.text)
        elif e.label_ == 'Edu_subject':
            dic_name['Edu_subject'].append(e.text)
        elif e.label_ == 'Graduation_year':
            dic_name['Graduation_year'].append(e.text)

def extract_info(cv_dir):
    extracted_info = []
    files = os.listdir(cv_dir)
    for file in files:
        if file.endswith('.pdf'):
            text = convert2txt.extract_text(cv_dir+file, '.pdf')
            result = create_dic(file)
            get_info(text, result)
            extracted_info.append(result)
        elif file.endswith('.doc'):
            text = convert2txt.extract_text(cv_dir+file, '.doc')
            result = create_dic(file)
            get_info(text, result)
            extracted_info.append(result)
        elif file.endswith('.docx'):
            text = convert2txt.extract_text(cv_dir+file, '.docx')
            result = create_dic(file)
            get_info(text, result)
            extracted_info.append(result)
        elif file.endswith('.txt'):
            with open(cv_dir+file, encoding='utf-8-sig') as f:
                text = f.read()
            result = create_dic(file)
            get_info(text, result)
            extracted_info.append(result)
    return extracted_info

def process(txt):
    data = txt
    data = re.sub(r'â+', ' ', data)
    data = re.sub(r'ï+', ' ', data)
    data = re.sub(r'\\u+', ' ', data)
    data = re.sub(r'â€+', ' ', data)
    data = re.sub(r'™+', ' ', data)
    data = re.sub(r'â€+', ' ', data)
    data = re.sub(r'â+', ' ', data)
    data = re.sub(r'\s+', ' ', data)
    return data

def create_csv_row_dic(headers, dic):
    result = {}
    for i in range(len(headers)):
        if i == 0:
            result[headers[i]] = dic[headers[i]]
        else:
            result[headers[i]] = ', '.join([process(i) for i in dic[headers[i]]])
    return result

def export_to_csv(csv_name, extracted_info):
    with open(csv_name, 'w', newline='', encoding="utf-8") as csv_file:
        headers = [
                'Filename',
                'Name',
                'Number',
                'Email',
                'Experience',
                'Companies',
                'Designation',
                'Responsibilities',
                'Skills',
                'Certification',
                'Degree',
                'Institution',
                'Edu_subject',
                'Graduation_year'
                ]
        writer = csv.DictWriter(csv_file, fieldnames=headers)
        writer.writeheader()
        for dic in extracted_info:
            write_dic = create_csv_row_dic(headers, dic)
            writer.writerow(write_dic)

export_to_csv('skills_report.csv', extract_info('../cv/txt/'))


import json

from test_tools.example_stubber import ExampleStubber

class OrganizationsStubber(ExampleStubber):
    """
    A class that implements a variety of stub functions that are used by the
    AWS Organizations unit tests.

    The stubbed functions all expect certain parameters to be passed to them as
    part of the tests, and will raise errors when the actual parameters differ from
    the expected.
    """

    def __init__(self, client, use_stubs=True):
        """
        Initializes the object with a specific client and configures it for
        stubbing or AWS passthrough.

        :param client: A Boto3 Organizations client.
        :param use_stubs: When True, use stubs to intercept requests. Otherwise,
                          pass requests through to AWS.
        """
        super().__init__(client, use_stubs)

    @staticmethod
    def _make_policy_summary(policy):
        return {
            "Id": policy["id"],
            "Arn": f'arn:aws:organizations::111111111111:policy/{policy["name"]}',
            "Name": policy["name"],
            "Description": policy["description"],
            "Type": policy["type"],
            "AwsManaged": False,
        }

    def stub_create_policy(self, policy, error_code=None):
        expected_parameters = {
            "Name": policy["name"],
            "Description": policy["description"],
            "Content": json.dumps(policy["content"]),
            "Type": policy["type"],
        }
        response = {
            "Policy": {
                "PolicySummary": self._make_policy_summary(policy),
                "Content": json.dumps(policy["content"]),
            }
        }
        self._stub_bifurcator(
            "create_policy", expected_parameters, response, error_code=error_code
        )

    def stub_list_policies(self, policy_filter, policies, error_code=None):
        expected_parameters = {"Filter": policy_filter}
        response = {"Policies": [self._make_policy_summary(pol) for pol in policies]}
        self._stub_bifurcator(
            "list_policies", expected_parameters, response, error_code=error_code
        )

    def stub_describe_policy(self, policy, error_code=None):
        expected_parameters = {"PolicyId": policy["id"]}
        response = {
            "Policy": {
                "PolicySummary": self._make_policy_summary(policy),
                "Content": json.dumps(policy["content"]),
            }
        }
        self._stub_bifurcator(
            "describe_policy", expected_parameters, response, error_code=error_code
        )

    def stub_attach_policy(self, policy_id, target_id, error_code=None):
        expected_parameters = {"PolicyId": policy_id, "TargetId": target_id}
        self._stub_bifurcator(
            "attach_policy", expected_parameters, error_code=error_code
        )

    def stub_detach_policy(self, policy_id, target_id, error_code=None):
        expected_parameters = {"PolicyId": policy_id, "TargetId": target_id}
        self._stub_bifurcator(
            "detach_policy", expected_parameters, error_code=error_code
        )

    def stub_delete_policy(self, policy_id, error_code=None):
        expected_parameters = {"PolicyId": policy_id}
        self._stub_bifurcator(
            "delete_policy", expected_parameters, error_code=error_code
        )


import json

import pytest
from api.processing import units
from unyt import unyt_quantity

def test_unyt_encoder():
    test_unyt_dict = {
        "test_quantity": unyt_quantity(5, "Mpc"),
    }

    expected = '{"test_quantity": "5 Mpc"}'
    assert expected == json.dumps(test_unyt_dict, cls=units.UnytEncoder)

def test_convert_swift_units_dict_types_success():
    test_units_dict = {
        "filename": "/a/test/file/path",
        "units": {
            "Unit current in cgs (U_I)": unyt_quantity(1.0, "statA"),
            "Unit length in cgs (U_L)": unyt_quantity(1e24, "cm"),
            "Unit mass in cgs (U_M)": unyt_quantity(1.9e43, "g"),
            "Unit temperature in cgs (U_T)": unyt_quantity(1.0, "K"),
            "Unit time in cgs (U_t)": unyt_quantity(1.09e19, "s"),
        },
        "mass": unyt_quantity(1.0e10, "Msun"),
        "length": unyt_quantity(1.0, "Mpc"),
        "time": unyt_quantity(1000.0, "Gyr"),
        "current": unyt_quantity(1.0, "statA"),
        "temperature": unyt_quantity(1.0, "K"),
    }

    retrieved_dict = units.convert_swift_units_dict_types(test_units_dict)

    for key, value in retrieved_dict.items():
        if isinstance(value, dict):
            for _subkey, subvalue in retrieved_dict[key].items():
                assert isinstance(subvalue, str)
        else:
            assert isinstance(value, str)

def test_convert_swift_units_dict_types_failure():
    test_units_dict = {
        "filename": "/a/test/file/path",
        "mass": unyt_quantity(1.0e10, "Msun"),
        "length": unyt_quantity(1.0, "Mpc"),
        "time": unyt_quantity(1000.0, "Gyr"),
        "current": unyt_quantity(1.0, "statA"),
        "temperature": unyt_quantity(1.0, "K"),
    }

    with pytest.raises(units.SWIFTUnytException):
        units.convert_swift_units_dict_types(test_units_dict)

def test_create_unyt_quantities_success():
    test_dict = {
        "filename": "/a/test/file/path",
        "units": {
            "Unit current in cgs (U_I)": "1.0 statA",
            "Unit length in cgs (U_L)": "1e+24 cm",
            "Unit mass in cgs (U_M)": "1.9e+43 g",
            "Unit temperature in cgs (U_T)": "1.0 K",
            "Unit time in cgs (U_t)": "1.09e+19 s",
        },
        "mass": "10000000000.0 Msun",
        "length": "1.0 Mpc",
        "time": "1000.0 Gyr",
        "current": "1.0 statA",
        "temperature": "1.0 K",
    }

    unyt_quantity_dict = units.create_unyt_quantities(test_dict)

    for key, value in unyt_quantity_dict.items():
        if isinstance(value, dict):
            for _subkey, subvalue in unyt_quantity_dict[key].items():
                assert isinstance(subvalue, unyt_quantity)
        elif key != "filename":
            assert isinstance(value, unyt_quantity)

def test_create_unyt_quantities_failure():
    test_dict = {
        "filename": "/a/test/file/path",
        "mass": "10000000000.0 Msun",
        "length": "1.0 Mpc",
        "time": "1000.0 Gyr",
        "current": "1.0 statA",
        "temperature": "1.0 K",
    }

    with pytest.raises(units.SWIFTUnytException):
        units.create_unyt_quantities(test_dict)


import flask
from flask import Flask, render_template, request, redirect
from web3 import Web3

app = Flask(__name__)

candidates = {1: "badi mohammad", 2: "hamza saht", 3: "omar hussein"}

# Connect to the Sepolia network
web3 = Web3(
    Web3.HTTPProvider(
        "https://eth-sepolia.g.alchemy.com/v2/ji4q9T9gKbrr9hk41agAd6JvmuvKhDJk"
    )
)

# Load the contract ABI and address
contract_address = "0x9eE6c65458701930770ADE3ACC9dE59437640b83"
contract_abi = [
    {"inputs": [], "stateMutability": "nonpayable", "type": "constructor"},
    {
        "inputs": [{"internalType": "uint8", "name": "_candidateId", "type": "uint8"}],
        "name": "vote",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
        "name": "candidates",
        "outputs": [
            {"internalType": "uint256", "name": "id", "type": "uint256"},
            {"internalType": "string", "name": "name", "type": "string"},
            {"internalType": "uint256", "name": "voteCount", "type": "uint256"},
        ],
        "stateMutability": "view",
        "type": "function",
    },
    {
        "inputs": [],
        "name": "candidatesCount",
        "outputs": [{"internalType": "uint8", "name": "", "type": "uint8"}],
        "stateMutability": "view",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "uint8", "name": "_candidateId", "type": "uint8"}],
        "name": "getCandidatesVoteCount",
        "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
        "stateMutability": "view",
        "type": "function",
    },
    {
        "inputs": [{"internalType": "address", "name": "", "type": "address"}],
        "name": "voters",
        "outputs": [{"internalType": "bool", "name": "", "type": "bool"}],
        "stateMutability": "view",
        "type": "function",
    },
]

# Instantiate the contract
contract = web3.eth.contract(address=contract_address, abi=contract_abi)

# Define the home route
@app.route("/")
def home():
    return render_template("index.html")

# Define a route to interact with the smart contract
@app.route("/interact", methods=["GET", "POST"])
def interact():
    if flask.request.method == "GET":
        badi = contract.functions.getCandidatesVoteCount(1).call()
        hamza = contract.functions.getCandidatesVoteCount(2).call()
        omar = contract.functions.getCandidatesVoteCount(3).call()
        return render_template("result.html", Badi=badi, Hamza=hamza, Omar=omar)
    elif flask.request.method == "POST":
        votedCandidate = request.form.get("name")
        for key in candidates:
            if votedCandidate.lower() in candidates[key]:
                votedCandidate = key
                break
        else:
            return render_template("index.html")

        print(contract.functions.vote(votedCandidate).call())
        return redirect("/interact", code=302)

if __name__ == "__main__":
    app.run(debug=True)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import m2m_changed
from django.core.mail import send_mail

import uuid
from time import sleep
import geocoder
import urllib3
urllib3.disable_warnings()

GENDER = (
    ('male', 'MALE'),
    ('female', 'FEMALE')
)

class Player(AbstractUser):
    avatar = models.CharField(max_length=100, default="default_avatar.png")
    birthday = models.DateField(null=True, blank=True)
    gender = models.CharField(max_length=20, choices=GENDER, default='male')
    address = models.CharField(max_length=255, blank=True, null=True)
    home_field = models.ForeignKey("Location", blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = 'Player'
        verbose_name_plural = 'Players'

    def __str__(self):
        return self.email

FACILITY_TYPE = (
    ('indoor', 'Indoor'),
    ('outdoor', 'Outdoor')
)

FIELD_TYPE = (
    ('grass', 'Grass'),
    ('turf', 'Turf'),
    ('futsal', 'Futsal')
)

class Location(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=255)
    facility_type = models.CharField(max_length=20, choices=FACILITY_TYPE, default='outdoor')
    field_type = models.CharField(max_length=20, choices=FIELD_TYPE, default='grass')
    url = models.CharField(max_length=120, null=True, blank=True)
    lat = models.FloatField(default=0)
    lng = models.FloatField(default=0)

    created_by = models.ForeignKey(Player, related_name="field_creator")
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

    def save(self, **kwargs):
        address = self.address.encode('utf-8')
        trial = 3

        while trial > 0:
            sleep(0.05)
            try:
                g = geocoder.google(address)
                latlon = g.geojson['features'][0]['geometry']['coordinates']
                self.lat = latlon[1]
                self.lng = latlon[0]
                break
            except (RuntimeError, ValueError, TypeError, Exception):
                trial = trial - 1

        super(Location, self).save()

class GameEvent(models.Model):
    location = models.ForeignKey(Location, related_name="events")
    datetime = models.DateTimeField()
    description = models.CharField(max_length=255, blank=True, null=True)
    players = models.ManyToManyField(Player)
    created_by = models.ForeignKey(Player, related_name="game_creator")

    def __str__(self):
        return self.location.name

class GameInvitation(models.Model):
    game = models.ForeignKey(GameEvent)
    player = models.ForeignKey(Player)
    code = models.CharField(max_length=50)
    is_accepted = models.BooleanField(default=False)

def notify_players(sender, instance, action, reverse, model, pk_set, **kwargs):
    if action == 'post_add':
        send_mail(
            'Game Event Notification',
            'You are invited to the game ({}) at {} {}'.format(instance.description, instance.location, instance.datetime),
            'info@goodfoot.club',
            [ii.email for ii in Player.objects.filter(id__in=pk_set)],
            fail_silently=False,
        )

# m2m_changed.connect(notify_players, sender=GameEvent.players.through)


# coding=utf-8
from django import forms
from django.db.models import Q
from django.forms.models import formset_factory

from BanBanTong.db import models

class RolePrivilegesForm(forms.ModelForm):

    class Meta:
        model = models.RolePrivilege
        exclude = ['uuid', 'role']

class RoleForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(RoleForm, self).__init__(*args, **kwargs)
        self.fields['name'].error_messages = {
            'required': u'请输入角色名！'
        }

    def clean(self):
        cleaned_data = super(RoleForm, self).clean()

        name = cleaned_data.get('name')

        # 判断角色名是否重复
        if name:
            existing = False
            if self.instance._state.adding:
                if models.Role.objects.filter(name=name).count() > 0:
                    existing = True
            else:
                if models.Role.objects.filter(~Q(uuid=self.instance.uuid),
                                              name=name).count() > 0:
                    existing = True
            if existing:
                self._errors['name'] = self.error_class([u'角色名已存在！'])

        return cleaned_data

    class Meta:
        model = models.Role
        exclude = ['uuid']

RolePrivilegesFormSet = formset_factory(RolePrivilegesForm)


import ipaddress
import math

class FirstSpyEstimator:
    def __init__(self, tx_maps, true_sources: {ipaddress.ip_address: [int]}):
        self.p = 0.0
        self.r = 0.0
        self.r_old = 0.0

        benign_nodes = len(true_sources)
        self.observer_map = {}  # BLOCK_ID: observer

        txs = sorted([item for sublist in list(true_sources.values()) for item in sublist])

        tx_ip_map = {}
        for tx in txs:
            first_time = math.inf
            for spy in tx_maps:
                spy_data = tx_maps[spy]
                obs_time = spy_data[tx][1]
                if obs_time < first_time:
                    first_time = obs_time
                    from_ip = spy_data[tx][0]
                    tx_ip_map[tx] = from_ip
                    self.observer_map[tx] = spy

            #print("Mapped TX %d to IP %s, first spy: %d" % (tx, from_ip, observer_map[tx]))

        self.ip_tx_map = {} # Mapping created by adversary

        for ip in true_sources.keys():
            self.ip_tx_map[ip] = []

        for tx, ip in tx_ip_map.items():
            if ip not in self.ip_tx_map:
                self.ip_tx_map[ip] = []
            self.ip_tx_map[ip].append(tx)

        for ip in true_sources.keys():
            fp = 0
            fn = 0
            tp = 0
            for tx in true_sources[ip]:
                if tx in self.ip_tx_map[ip]:
                    tp += 1
                else:
                    fn += 1

            if tp == 0:
                continue
            for tx in self.ip_tx_map[ip]:
                if tx not in true_sources[ip]:
                    fp += 1

            self.r += tp/(tp+fn)
            self.p += tp/(tp+fp)

        #print(len(true_sources.keys()))
        t_s = len(true_sources.keys())
        self.r = self.r/t_s
        self.p = self.p/t_s


import numpy as np
import pandas as pd
import csv
from datetime import datetime, timedelta
from polygon import RESTClient
import yfinance as yf
import matplotlib.pyplot as plt

d2 = datetime.today() - timedelta(days=1)
d1 = d2 - timedelta(days=365)
d3 = d2 - timedelta(days=30)
start_d = d1.strftime('%Y-%m-%d')
end_d = d2.strftime('%Y-%m-%d')
rsi_d = d3.strftime('%Y-%m-%d')

def movingAverages(ticker, time_frame, key, s_sma_days = 50, l_sma_days = 200, s_ema_days = 12, l_ema_days = 26, smoothing = 2):
    #dates for polygon api
    start_d = datetime.today() - timedelta(days=365)
    end_d = datetime.today()

    #array with short and long simple moving average
    sma = [[], []]
    #array with short and long exponential moving average
    ema = [[], []]

    #use polygon to get market data from start to end date
    with RESTClient(key) as client:
        bars = client.stocks_equities_aggregates(ticker, 1, 'day', start_d.strftime('%Y-%m-%d'), end_d.strftime('%Y-%m-%d'))

        try:
            data = bars.results
            prices = []
            for dataset in data:
                prices.append(dataset['c'])
            volume = data[-2]['v']
        except:
            prices = []
            volume = 0

    #reverses array so newer prices occur first
    prices = prices[::-1]

    #checks if stock has enough historical data / enough data points
    if len(prices) < l_sma_days+time_frame+1:
        #returns empty arrays to be checked later
        return [sma, ema]

    #calculates the short simple ma for the time designated in time_frame
    for x in range(time_frame):
        sum = 0
        i = 0
        for y in range(x, s_sma_days + x):
            if i == s_sma_days:
                break
            sum += prices[y]
            i += 1
        sma[0].append(sum/s_sma_days)

    #calculates the long simple ma for the time designated in time_frame
    for x in range(time_frame):
        sum = 0
        i = 0
        for y in range(x, l_sma_days + x):
            if i == l_sma_days:
                break
            sum += prices[y]
            i += 1
        sma[1].append(sum/l_sma_days)

    #sample short sma to be used in ema calculation
    sum = 0
    for x in range(time_frame, time_frame + s_ema_days):
        sum += prices[x]
    samp_s_sma = sum / (s_ema_days)

    #sample long sma to be used in ema calculation
    sum = 0
    for x in range(time_frame, time_frame + l_ema_days):
        sum += prices[x]
    samp_l_sma = sum / (l_ema_days)

    s_factor = (smoothing / (1 + s_ema_days))
    l_factor = (smoothing / (1 + l_ema_days))

    #goes backwards through time_frame, calculating each more recent short term EMA
    for x in reversed(range(0, time_frame)):
        if x == time_frame - 1:
            ema[0].append(prices[x] * s_factor + samp_s_sma * (1 - s_factor))
        else:
            ema[0].append(prices[x] * s_factor + ema[0][-1] * (1 - s_factor))
    #same process for long term EMAs
    for x in reversed(range(0, time_frame)):
        if x == time_frame - 1:
            ema[1].append(prices[x] * l_factor + samp_l_sma * (1 - l_factor))
        else:
            ema[1].append(prices[x] * l_factor + ema[1][-1] * (1 - l_factor))

    #reverses ema lists
    ema[0] = ema[0][::-1]
    ema[1] = ema[1][::-1]

    #plt.figure(1)
    #plt.plot(ema[0])
    #plt.plot(ema[1])

    #plt.show()

    #returns SMA and EMA
    return [sma, ema, volume]

def buySignal(ticker, time_frame, key, smoothing=2):

    #get simple moving averages and assign each into list for comprehensibility
    ma = movingAverages(ticker, time_frame, key)
    s_sma = ma[0][0]
    l_sma = ma[0][1]

    s_ema = ma[1][0]
    l_ema = ma[1][1]

    #makes sure data isnt invalid
    if len(s_sma) == 0:
        return None
    if len(s_ema) == 0:
        return None

    #getting the moving average convergence divergence (macd) line
    macd_line = []
    for x in range(len(s_ema)):
        macd_line.append(s_ema[x] - l_ema[x])

    #prior macd used for last signal line calculation
    samp_macd = macd_line[-1] - (macd_line[-2] - macd_line[-1])

    #create signal line as ema of past 9 macds
    sig_line = []
    sig_days = 9

    for x in reversed(range(0, time_frame)):
        if x == time_frame - 1:
            sig_line.append(macd_line[x] * (smoothing / (1 + sig_days)) + samp_macd * (1 - (smoothing / (1 + sig_days))))

        else:
            sig_line.append(macd_line[x] * (smoothing / (1 + sig_days)) + sig_line[time_frame-2-x] * (1 - (smoothing / (1 + sig_days))))

    #turn macd and signal to displau old --> new on graph
    macd_line = macd_line[::-1]

    #plt.figure(1)
    #plt.plot(macd_line, 'r')
    #plt.plot(sig_line, 'b')
    #plt.show()

    #check if macd is increasing
    macd_signal = None
    #see if macd crosses signal within time frame
    for x in range(1, time_frame):
        if macd_line[x-1] - sig_line[x-1] < 0 and macd_line[x] - sig_line[x] > 0:
            macd_signal = True
        elif macd_line[x-1] - sig_line[x-1] > 0 and macd_line[x] - sig_line[x] < 0:
            macd_signal = False

    #check if golden cross happened recently
    golden_sma = s_sma[0] > l_sma[0]
    golden_ema =  s_ema[0] > s_sma[0]

    #checks if these crosses happened recentl
    rcent1 = False
    rcent2 = False
    for x in range(time_frame):
        if golden_sma and (s_sma[x] <= l_sma[x]) and rcent1 == False:
            rcent1 = True
        elif golden_ema and (s_ema[x] <= l_ema[x]) and rcent2 == False:
            rcent2 = True

    #if short-term mas are increasing
    inc_sma = ((s_sma[0] - s_sma[time_frame - 1]) / time_frame) > 0
    inc_ema = ((s_ema[0] - s_sma[time_frame - 1]) / time_frame) > 0

    #makes sure there is enough volume
    vol = ma[2] > 75000

    #print(golden_sma)
    #print(rcent1)
    #print(golden_ema)
    #print(rcent2)
    #print(inc_sma)
    #print(inc_ema)
    #print(vol)
    #print(macd_signal)

    #plt.figure(2)
    #plt.plot(s_sma, 'r')
    #plt.plot(l_sma, 'b')

    #plt.show()

    if (golden_sma and rcent1) and inc_sma and vol and macd_signal == True: #or (golden_ema and rcent2))
        return 'buy'

def sellSignal(ticker, time_frame, key):

    #Stochastic is above 85ish
    #RSI above 70%
    #stop loss under 20%

    #is the ema stalling
    ma = movingAverages(ticker, time_frame, key)
    short_ema = ma[1][0]
    sma = ma[0][0]
    ema_stall = False
    if short_ema[0] < short_ema[-1]:
        ema_stall = True

    #get data for stochastic oscillator
    data = yf.download(tickers = ticker, period= '1mo', interval='30m')
    prices = data['Close'].tolist()
    prices = prices[::-1]

    #calculate fast stochastic oscillator, slow stochastic oscillator
    fast_indexs = []
    days= 0
    for x in range(1, len(prices)-1):
        if days == time_frame*16:
            break
        lastC = prices[x-1]
        low14 = min(prices[x:142+x])
        high14 = max(prices[x:142+x])
        stoch_ind = ((lastC - low14) / (high14 - low14)) * 100
        fast_indexs.append(stoch_ind)
        days+=1

    slow_indexs = []
    for x in range(0, time_frame):
        slow_indexs.append(sum(fast_indexs[x:39+x]) / 39)

    stochastic = False
    for val in slow_indexs:
        if val > 85:
            stochastic = True

    #get RSI
    rsi = True #change to false once finished
    #with RESTClient(key) as client:
    #    bars = client.stocks_equities_aggregates(ticker, 1, 'day', rsi_d.strftime('%Y-%m-%d'), end_d.strftime('%Y-%m-%d'))
    #    try:
    #        data = bars.results
    #        opens = []
    #        closes = []
    #        for dataset in data:
    #            opens.append(dataset['o'])
    #            closes.append(dataset['c'])
    #    except:
    #        opens = []
    #        closes = []

    #for x in range(opens):

    if ema_stall and stochastic == True and rsi == True:
        return 'sell'

    return None


'''
Lex Strings

Name: <your name>
'''
from collections import Counter, defaultdict

#
# Complete the 'rearrangedString' function below.
#
# The function is expected to return a STRING.
# The function accepts following parameters:
#  1. STRING s
#

# 1. This function will filter the alphanumeric characters from the string and sort them.
def filter_and_sort(s):
    alphanumeric_chars_list = [ch for ch in s if ch.isalnum()]
    alphanumeric_chars = ''.join(alphanumeric_chars_list)
    return sorted(alphanumeric_chars, reverse=True)

# 2. This function will take the sorted string and group the characters by their count.
def group_by_count(sorted_chars):
    char_count = Counter(sorted_chars)
    groups = defaultdict(list)
    for char, count in sorted(char_count.items(), key=lambda x: (-x[1], x[0])):
        groups[count].append(char)
    return groups

# 3. This function will take the groups and apply the alternating sort order.
def alternate_sort(groups):
    sorted_groups = []
    ascending_order = True
    for count, chars in sorted(groups.items(), reverse=True):
        chars = ''.join(chars)
        if not ascending_order:
            chars = chars[::-1]
        sorted_groups.append((count, chars))
        ascending_order = not ascending_order
    return sorted_groups

# 4.
def format_result(sorted_groups):
    return ','.join(f"{count}{chars}" for count, chars in sorted_groups)

def rearrangedString(s):
    # Write your code here
    '''
    1. Extract alphanumeric characters: We'll start by extracting only alphanumeric characters from the input string.
    2. Create frequency groups: We'll group characters by their frequency, preserving the order of characters within each group.
    3. Sort and alternate groups: We'll sort the groups by frequency, and then apply the alternating order rule within each group.
    4. Concatenate and format: Finally, we'll concatenate the groups and format the result as required.
    '''
    sorted_chars = filter_and_sort(s)
    groups = group_by_count(sorted_chars)
    sorted_groups = alternate_sort(groups)
    result = format_result(sorted_groups)

if __name__ == '__main__':
    import sys

    sys.stdin = open('lex_strings_sample_data.txt', 'r')
    for tc in range(10):
        s = input()
        result = rearrangedString(s)
        print('Test Case #{}: {}'.format(tc + 1, result))

'''
Your output on console should be:
Test Case #1: 6in,4ts,3aegr,2o,1ESTfhlmpx
Test Case #2: 5a,4se,3r,2tonkihc,1ACFHLRSdflmuwy
Test Case #3: 2135ei,1tsrohgfdaTPI9642
Test Case #4: 7es,4lh,2a,1ytrobS
Test Case #5: 8a,5n,4gu,3rlic,2CPSdehmosty,1vbVRJIBA
Test Case #6: 7ae,6ni,5t,4rhd,3gl,2vsoc,119CDIOVbmpuwy
Test Case #7: 9e,5nica,4or,3th,202CTsu,1vpmlfdSA
Test Case #8: 53,472,345689deo,2trni1,1IPTafghsu
Test Case #9: 14e,13p,7i,6r,5cdk,4P,2alost,1ywnmfH
Test Case #10: 8o,7e,5hn,3wtsrda,2ikp,1ylfbT10
'''


import pygame
from pygame.surface import Surface

import sys

from Screens.Content import Content, State
from Options.Options import KEY_REPEAT_DELAY, KEY_REPEAT_INTERVAL, TITLE_H_START, TITLE_W_START, TITLE_H_SIZE, BUTTON_H, BUTTON_W, FONT, BRICK_SIZE, ICON_H, ICON_W
from Options.Colors import Colors, Color_mod

class Settings(Content):
    def __init__(self) -> None:
        self.options_1: list[str] = [
                'Next tetr',
                'Tetr. shadow',
                'Fps',
                'Fall Speed',
                'LockDelay'
                ]
        self.options_2: list[str] = [
                'Key Rep. Interval',
                'Key Rep. Delay',
                'Soft Drop',
                'Return'
                ]
        self.border: int = (TITLE_H_SIZE - (len(self.options_1) * BUTTON_H)) // (2 * len(self.options_1))

    def update(self, display: Surface) -> State:
        # Remover e colocar em opcoes no Title()
        for e in pygame.event.get():
            if e.type == pygame.MOUSEBUTTONDOWN:
                return State.Title
        pygame.key.set_repeat(KEY_REPEAT_DELAY, KEY_REPEAT_INTERVAL)
        return State.Stay

    def draw(self, display: Surface) -> None:
        self.draw_buttons(display)

    def draw_buttons(self, display) -> None:
        for i in range(len(self.options_1)):
            pygame.draw.rect(display,
                             Colors.PURPLE.value,
                             (TITLE_W_START - (3 * BUTTON_W // 4),
                              TITLE_H_START // 2 + (i * (BUTTON_H + self.border)),
                              BUTTON_W,
                              BUTTON_H // 2))
            pygame.draw.rect(display,
                             Color_mod().get_shadow_from_color(Colors.PURPLE),
                             (TITLE_W_START - (3 * BUTTON_W // 4),
                              TITLE_H_START // 2 + (i * (BUTTON_H + self.border)) + (BUTTON_H // 2),
                              BUTTON_W,
                              BUTTON_H // 2))
            pygame.draw.rect(display,
                             Color_mod().get_light_from_color(Colors.PURPLE),
                             (TITLE_W_START - (3 * BUTTON_W // 4),
                              TITLE_H_START // 2 + (i * (BUTTON_H + self.border)),
                              BUTTON_W,
                              BUTTON_H),
                             width=4)
            button_text: Surface = FONT.render(self.options_1[i], True, Colors.WHITE.value)
            display.blit(button_text, (TITLE_W_START - (3 * BUTTON_W // 4) + (BUTTON_H // 2), TITLE_H_START // 2 + (i * (BUTTON_H + self.border))))
        for i in range(len(self.options_2)):
            pygame.draw.rect(display,
                             Colors.PURPLE.value,
                             (TITLE_W_START + (3 * BUTTON_W // 4),
                              TITLE_H_START // 2 + (i * (BUTTON_H + self.border)),
                              BUTTON_W,
                              BUTTON_H // 2))
            pygame.draw.rect(display,
                             Color_mod().get_shadow_from_color(Colors.PURPLE),
                             (TITLE_W_START + (3 * BUTTON_W // 4),
                              TITLE_H_START // 2 + (i * (BUTTON_H + self.border)) + (BUTTON_H // 2),
                              BUTTON_W,
                              BUTTON_H // 2))
            pygame.draw.rect(display,
                             Color_mod().get_light_from_color(Colors.PURPLE),
                             (TITLE_W_START + (3 * BUTTON_W // 4),
                              TITLE_H_START // 2 + (i * (BUTTON_H + self.border)),
                              BUTTON_W,
                              BUTTON_H),
                             width=4)
            button_text: Surface = FONT.render(self.options_2[i], True, Colors.WHITE.value)
            display.blit(button_text, (TITLE_W_START + (3 * BUTTON_W // 4) + (BUTTON_H // 2), TITLE_H_START // 2 + (i * (BUTTON_H + self.border))))


import threading
import time
import serial.tools.list_ports
from os import environ
from re import search

from PyQt6.QtCore import QObject, pyqtSignal

from UM.Platform import Platform
from UM.Signal import Signal, signalemitter
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
from UM.i18n import i18nCatalog

from cura.PrinterOutput.PrinterOutputDevice import ConnectionState

from . import USBPrinterOutputDevice

i18n_catalog = i18nCatalog("cura")

@signalemitter
class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
    """Manager class that ensures that an USBPrinterOutput device is created for every connected USB printer."""

    addUSBOutputDeviceSignal = Signal()
    progressChanged = pyqtSignal()

    def __init__(self, application, parent = None):
        if USBPrinterOutputDeviceManager.__instance is not None:
            raise RuntimeError("Try to create singleton '%s' more than once" % self.__class__.__name__)

        super().__init__(parent = parent)
        USBPrinterOutputDeviceManager.__instance = self

        self._application = application

        self._serial_port_list = []
        self._usb_output_devices = {}
        self._usb_output_devices_model = None
        self._update_thread = threading.Thread(target = self._updateThread)
        self._update_thread.daemon = True

        self._check_updates = True

        self._application.applicationShuttingDown.connect(self.stop)
        # Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
        self.addUSBOutputDeviceSignal.connect(self.addOutputDevice)

        self._application.globalContainerStackChanged.connect(self.updateUSBPrinterOutputDevices)

    # The method updates/reset the USB settings for all connected USB devices
    def updateUSBPrinterOutputDevices(self):
        for device in self._usb_output_devices.values():
            if isinstance(device, USBPrinterOutputDevice.USBPrinterOutputDevice):
                device.resetDeviceSettings()

    def start(self):
        self._check_updates = True
        self._update_thread.start()

    def stop(self, store_data: bool = True):
        self._check_updates = False

    def _onConnectionStateChanged(self, serial_port):
        if serial_port not in self._usb_output_devices:
            return

        changed_device = self._usb_output_devices[serial_port]
        if changed_device.connectionState == ConnectionState.Connected:
            self.getOutputDeviceManager().addOutputDevice(changed_device)
        else:
            self.getOutputDeviceManager().removeOutputDevice(serial_port)

    def _updateThread(self):
        while self._check_updates:
            container_stack = self._application.getGlobalContainerStack()
            if container_stack is None:
                time.sleep(5)
                continue
            port_list = []  # Just an empty list; all USB devices will be removed.
            if container_stack.getMetaDataEntry("supports_usb_connection"):
                machine_file_formats = [file_type.strip() for file_type in container_stack.getMetaDataEntry("file_formats").split(";")]
                if "text/x-gcode" in machine_file_formats:
                    # We only limit listing usb on windows is a fix for connecting tty/cu printers on MacOS and Linux
                    port_list = self.getSerialPortList(only_list_usb=Platform.isWindows())
            self._addRemovePorts(port_list)
            time.sleep(5)

    def _addRemovePorts(self, serial_ports):
        """Helper to identify serial ports (and scan for them)"""

        # First, find and add all new or changed keys
        for serial_port in list(serial_ports):
            if serial_port not in self._serial_port_list:
                self.addUSBOutputDeviceSignal.emit(serial_port)  # Hack to ensure its created in main thread
                continue
        self._serial_port_list = list(serial_ports)

        for port, device in self._usb_output_devices.items():
            if port not in self._serial_port_list:
                device.close()

    def addOutputDevice(self, serial_port):
        """Because the model needs to be created in the same thread as the QMLEngine, we use a signal."""

        device = USBPrinterOutputDevice.USBPrinterOutputDevice(serial_port)
        device.connectionStateChanged.connect(self._onConnectionStateChanged)
        self._usb_output_devices[serial_port] = device
        device.connect()

    def getSerialPortList(self, only_list_usb = False):
        """Create a list of serial ports on the system.

        :param only_list_usb: If true, only usb ports are listed
        """
        base_list = []
        try:
            port_list = serial.tools.list_ports.comports()
        except TypeError:  # Bug in PySerial causes a TypeError if port gets disconnected while processing.
            port_list = []
        for port in port_list:
            if not isinstance(port, tuple):
                port = (port.device, port.description, port.hwid)
            if not port[2]:  # HWID may be None if the device is not USB or the system doesn't report the type.
                continue
            if only_list_usb and not port[2].startswith("USB"):
                continue

            # To prevent cura from messing with serial ports of other devices,
            # filter by regular expressions passed in as environment variables.
            # Get possible patterns with python3 -m serial.tools.list_ports -v

            # set CURA_DEVICENAMES=USB[1-9] -> e.g. not matching /dev/ttyUSB0
            pattern = environ.get('CURA_DEVICENAMES')
            if pattern and not search(pattern, port[0]):
                continue

            # set CURA_DEVICETYPES=CP2102 -> match a type of serial converter
            pattern = environ.get('CURA_DEVICETYPES')
            if pattern and not search(pattern, port[1]):
                continue

            # set CURA_DEVICEINFOS=LOCATION=2-1.4 -> match a physical port
            # set CURA_DEVICEINFOS=VID:PID=10C4:EA60 -> match a vendor:product
            pattern = environ.get('CURA_DEVICEINFOS')
            if pattern and not search(pattern, port[2]):
                continue

            base_list += [port[0]]

        return list(base_list)

    __instance = None # type: USBPrinterOutputDeviceManager

    @classmethod
    def getInstance(cls, *args, **kwargs) -> "USBPrinterOutputDeviceManager":
        return cls.__instance