from django.db import models
from wagtail.wagtailadmin.edit_handlers import FieldPanel
from wagtail.wagtailcore.fields import RichTextField
from wagtail.wagtailcore.models import Page
from wagtailsettings import BaseSetting, register_setting

class RevolvCustomPage(Page):
    """
    A CMS page representing a web page that the RE-volv administrators might
    be able to dynamically update, such as "About Us", "Former Projects",
    etc.

    How wagtail works is that there exists a hierarchy of pages, and each page
    inherits from Page like this one does (there's one root page for every site).
    Pages can have children that are of any subclass of Page, and thus RevolvCustomPages
    can be at any level in the menu hierarchy which we need for both the header
    and footer menus.
    """
    body = RichTextField()
    search_name = "Custom Page"

    indexed_fields = ('body', )
    content_panels = [
        FieldPanel('title', classname="full title"),
        FieldPanel('body', classname="full"),
    ]

class RevolvLinkPage(Page):
    """
    A page that represents a link to another page. Since it is technically
    a "Page", it can go into menus and have children, but it does not have
    content. A RevolvLinkPage exists for menu headers which serve as only
    links to other pages, not pages themselves, and menu items that serve as
    outside links or links to pages that are not part of the CMS, like sign in
    or auth.
    """
    link_href = models.CharField(max_length=1024)
    content_panels = [
        FieldPanel('title', classname="full title"),
        FieldPanel('link_href', classname="full")
    ]

@register_setting
class MainPageSettings(BaseSetting):
    """
    Editable settings for the homepage.

    See https://wagtailsettings.readthedocs.org/en/latest/settings.html
    """
    site_tagline = models.CharField(
        max_length=100,
        help_text="The tagline for the site, which will be shown large and centered over the animated cover video.",
        default="STOP IMAGINING A CLEAN ENERGY FUTURE. START CREATING IT."
    )
    site_subheading = models.TextField(
        help_text="The description text that will be shown after the site tagline - a brief (one sentence) introduction to what RE-volv is and how donors can help.",
        default="When you donate to RE-volv's solar projects, you are making a lasting impact on the environment and the world around you."
    )
    learn_button_text = models.CharField(
        max_length=50,
        help_text="The label on the 'Learn more button'. E.g. 'Learn about how RE-volv works'",
        default="DONATE"
    )
    single_project_heading = models.CharField(
        max_length=50,
        help_text="The heading to display above the featured project on the homepage when there is only one featured project, e.g. 'Our current project'",
        default="OUR CURRENT PROJECT"
    )
    multiple_projects_heading = models.CharField(
        max_length=50,
        help_text="The heading to display above the featured project on the homepage when there are multiple featured projects, e.g. 'Our current projects'",
        default="OUR CURRENT PROJECTS"
    )
    how_it_works_heading = models.CharField(
        max_length=50,
        help_text="The heading to display above the 'Learn about how RE-volv works' section on the homepage, e.g. 'Learn about how RE-volv works'",
        default="How it works"
    )
    how_it_works_intro = models.TextField(
        help_text="Intro paragraph for the 'Learn about how RE-volv works' section of the homepage.",
        default=(
            "We believe that everyone should have the ability to support clean energy. So we "
            "created a new way for people to take action. It's a pretty simple idea. We raise "
            "money through crowdfunding to put solar panels on community-serving "
            "nonprofit organizations and worker-owned cooperatives. As these organizations "
            "pay us back, we reinvest the money into more solar projects in communities "
            "across the country. This creates a revolving fund for solar energy that continually "
            "perpetuates itself building more and more solar. It's a pay-it-forward model for "
            "community solar. We call it the Solar Seed Fund."
       )
    )
    how_it_works_video_url = models.URLField(help_text="URL for 'how it works' video", default="https://www.youtube.com/embed/eSADOAxjcPU")
    how_it_works_tagline = models.CharField(
        max_length=200,
        help_text="Large heading directly before the infograph portion of the homepage. e.g. 'How would your donation help?'",
        default="How would your donation to RE-volv help?"
    )
    how_it_works_pitch = models.CharField(
        max_length=200,
        help_text="Large text directly before the call to action donation button at the bottom of the hompage, e.g. 'Be part of something great.'",
        default="Be a part of something great."
    )
    call_to_action_button_text = models.CharField(
        max_length=50,
        help_text="The label on the green call to action button at the bottom of the homepage.",
        default="Start contributing"
    )

@register_setting
class FooterSettings(BaseSetting):
    """Editable settings for the RE-volv footer."""
    contact_heading = models.CharField(
        max_length=50,
        help_text="The heading to display in the footer menu above the contact information. Probably just 'Contact'",
        default="Contact"
    )
    contact_email = models.EmailField(
        max_length=200,
        help_text="The email address to display in the contact info section of the footer menu.",
        default="info@re-volv.org"
    )
    contact_phone_number = models.CharField(
        max_length=30,
        help_text="The phone number to display in the contact info section of the footer menu. e.g. 415.314.7719",
        default="415.314.7719"
    )
    contact_address_line_1 = models.CharField(
        max_length=150,
        help_text="The first line of the address to display in the contact info section of the footer menu.",
        default="972 Mission St. Suite 500"
    )
    contact_address_line_2 = models.CharField(
        blank=True,
        max_length=150,
        help_text="The second line of the address to display in the contact info section of the footer menu.",
        default="San Francisco, CA 94103"
    )

@register_setting
class LoginPageSettings(BaseSetting):
    """Editable settings for the RE-volv login page."""
    heading = models.CharField(
        max_length=50,
        help_text="The heading text of the login page. e.g. 'Welcome back!'",
        default="Welcome back!"
    )
    heading_for_donation = models.CharField(
        max_length=30,
        help_text="The heading text of the login page when specifically directed there as a consequence of clicking a donate button when not logged in. e.g. 'Please log in to donate'",
        default="Login to donate"
    )
    login_paragraph = RichTextField(
        blank=True,
        help_text="The paragraph of text to be shown under the heading on the login page, but before the links to the register page and the forgot password page.",
        default="
Log in to see the impact you've had on communities that use renewable solar energy.
"
    )
    login_paragraph_for_donation = RichTextField(
        blank=True,
        help_text="The paragraph of text to be shown under the heading on the login page, but specifically when the user is directed to the login page as a result of clicking a donate button when not logged in.",
        default=""
    )
    button_text = models.CharField(
        max_length=30,
        help_text="The text on the actual login button, e.g. 'Log in'",
        default="Log in"
    )

    content_panels = [
        FieldPanel('login_paragraph', classname="full"),
        FieldPanel('login_paragraph_for_donation', classname="full"),
    ]

@register_setting
class SignupPageSettings(BaseSetting):
    """Editable settings for the RE-volv signup (user regisration) page."""
    heading = models.CharField(
        max_length=50,
        help_text="The heading text of the sign up page. e.g. 'Welcome!'",
        default="Welcome!"
    )
    signup_paragraph = RichTextField(
        blank=True,
        help_text="The paragraph of text to be shown under the heading on the sign up page, but before the link to the login page.",
        default="
Start investing in renewable solar energy by signing up for an account.
"
    )
    tos_paragraph = RichTextField(
        blank=True,
        help_text="The paragraph to display directly after the form but before the sign up button. Should include a link to the Terms of Service page.",
        default="
Signing up for an account means joining the RE-volv community and agreeing to the terms of service. RE-volv will never store credit card information and will never give your information to third parties. Welcome!
"
    )
    button_text = models.CharField(
        max_length=30,
        help_text="The text on the actual sign up button, e.g. 'Sign up'",
        default="Sign Up"
    )

    content_panels = [
        FieldPanel('signup_paragraph', classname="full"),
    ]

@register_setting
class ProjectPageSettings(BaseSetting):
    """Editable settings for the RE-volv project page."""
    donors_wording = models.CharField(
        max_length=20,
        help_text="The wording that will be displayed after the number of donors to the project the user is viewing. For example, 'donors' or 'contributors'.",
        default="donors"
    )

@register_setting
class PaymentModalSettings(BaseSetting):
    """Editable settings for the payment modal on the project page."""
    payment_modal_paragraph = RichTextField(
        blank=True,
        help_text="Optional: a paragraph which will appear above the credit card entry areas of the donation modal on the project page. Use this as another opportunity to assure the user of the security of the payments.",
        default=""
    )
    confirm_payment_paragraph = RichTextField(
        blank=True,
        help_text="Optional: a paragraph which will appear above the submit button of the donation confirmation modal on the project page. Use this as another opportunity to assure the user of the security of the payments.",
        default=""
    )

    content_panels = [
        FieldPanel('payment_modal_paragraph', classname="full"),
    ]

@register_setting
class DashboardImpactSettings(BaseSetting):
    """Editable settings for the 'My Impact' section of the dashboard page."""
    impact_statistics_header_text = models.CharField(
        max_length=90,
        help_text="The heading above the statistics in the 'My Impact' section of the dashboard, e.g. 'Thank you for contributing! Your contribution has...'.",
        default='Thank you for contributing! Your contribution has...'
    )

    description_section_explanation = ' There are three sections to every statistic description. The top section is the first line, the middle section is the actual statistic (which is calculated and not editable) and is shown bold and in color, and the bottom section is the last line.'

    repayment_statistic_top_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The top section of the description of the repayments statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='earned'
    )

    repayment_statistic_bottom_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The bottom section of the description of the repayments statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='to reinvest'
    )

    project_count_statistic_top_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The top section of the description of the project count statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='contributed to'
    )

    project_count_statistic_bottom_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The bottom section of the description of the project count statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default=''
    )

    carbon_dioxide_statistic_top_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The top section of the description of the carbon dioxide statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='saved'
    )

    carbon_dioxide_statistic_bottom_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The bottom section of the description of the carbon dioxide statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='of carbon dioxide'
    )

    last_statistic_description_text = models.CharField(
        blank=True,
        max_length=100,
        help_text="The description of the bottom right icon on the 'My Impact' section of the dashboard. Unlike the other statistics on this page, this last section only has one text field.",
        default='Help us save the world by going solar!'
    )

    trees_saved_statistic_top_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The top section of the description of the trees saved statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='saved'
    )

    trees_saved_statistic_bottom_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The bottom section of the description of the trees saved statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='of trees'
    )

    kwh_statistic_top_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The top section of the description of the kilowatt-hours statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='generated'
    )

    kwh_statistic_bottom_description_text = models.CharField(
        blank=True,
        max_length=20,
        help_text="The bottom section of the description of the kilowatt-hours saved statistic on the 'My Impact' section of the dashboard." + description_section_explanation,
        default='of electricity'
    )

@register_setting
class DashboardSettings(BaseSetting):
    """Editable settings for the dashboard page."""

    category_preferences_header_text = models.CharField(
        max_length=100,
        help_text="The heading of category preferences section in the 'My Impact' section of the dashboard.",
        default='What type of projects should we invest your repayments in next?'
    )

    category_preferences_explanation_header_text = models.CharField(
        max_length=50,
        help_text="The header of the category preference explanation in the 'My Impact' section of the dashboard.",
        default="What's going on?"
    )

    category_preferences_explanation_paragraph = RichTextField(
        help_text="A paragraph which will appear below the category preference options on the 'My Impact' section on the dashboard to explain to the user what category preferences mean.",
        default="
Your donation to RE-volv has been invested in a revolving fund. Money from the fund is used to place solar equipment on community buildings. Over time, the community pays RE-volv back. These repayments are invested in even more solar projects. A fraction of the repayments from a solar investment originates from your investment. Your preferences directly affect where that chunk of money is invested.
"
    )

@register_setting
class ProjectStatisticsSettings(BaseSetting):
    """Editable settings for statistics about projects (see revolv.project.stats)"""
    kilowatt_description = models.CharField(
        max_length=50,
        help_text="A description of the concept of kilowatts of power that a project generates, to be displayed as a statistic on the dashboard or project pages. e.g. 'Kilowatt power output'",
        default="Kilowatt power output"
    )
    dollars_saved_description = models.CharField(
        max_length=50,
        help_text="A description of the dollars that a project will save in elctricity costs per month, to be displayed as a statistic on the dashboard or project pages. e.g. 'Dollars saved per month'",
        default="Dollars saved per month"
    )
    carbon_saved_description = models.CharField(
        max_length=50,
        help_text="A description of the pounds of carbon that will be saved by a project per month, to be displayed as a statistic on the dashboard or project pages. e.g. 'Carbon emissions saved per month'",
        default="Carbon emissions saved per month"
    )
    trees_description = models.CharField(
        max_length=50,
        help_text="A description of the acres of trees which, if planted, would provide equivalent savings to a project, to be displayed as a statistic on the dashboard or project pages. e.g. 'Equivalent carbon savings in trees'",
        default="Equivalent carbon savings of trees"
    )
    automobile_miles_description = models.CharField(
        max_length=50,
        help_text="A description of the equivalent automobile miles which, if driven, would produce the same amount of carbon that a project will save per month, to be displayed as a statistic on the dashboard or project pages. e.g. 'Equivalent carbon in automobile miles'",
        default="Equivalent carbon in automobile miles"
    )
    donor_stats_table_funding_goal_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the funding goal statistic in the dashboard project statistics area.",
        default="Funding Goal"
    )
    donor_stats_table_amount_donated_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the amount donated statistic in the dashboard project statistics area.",
        default="Amount Donated"
    )
    donor_stats_table_amount_remaining_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the amount remaining statistic in the dashboard project statistics area.",
        default="Amount Remaining"
    )
    donor_stats_table_donors_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the number of donors statistic in the dashboard project statistics area. e.g. 'Donors' or 'Total Donors'",
        default="Donors"
    )
    donor_stats_table_timeline_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the project timeline (total number of days for the campaign) statistic in the dashboard project statistics area. e.g. 'Timeline'",
        default="Timeline"
    )
    donor_stats_table_days_so_far_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the 'days so far' statistic in the dashboard project statistics area. e.g. 'Days so far' or 'Days since start'",
        default="Days so far"
    )
    repayment_stats_table_amount_repaid_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the amount repaid statistic in the dashboard project repayment statistics area.",
        default="Amount Repaid"
    )
    repayment_stats_table_amount_donated_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the amount donated statistic in the dashboard project repayment statistics area.",
        default="Amount Donated"
    )
    repayment_stats_table_kwh_saved_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the kwh saved statistic in the dashboard project repayment statistics area.",
        default="Amount Remaining"
    )
    people_affected_description = models.CharField(
        max_length=30,
        help_text="The description to be displayed next to the 'people affected' statistic in the dashboard project statistics area. e.g. 'Number of people affected' or 'People affected'",
        default="Number of people affected"
    )

@register_setting
class ActiveProjectsPageSettings(BaseSetting):
    """
    Editable settings for the Projects List Page.

    See https://wagtailsettings.readthedocs.org/en/latest/settings.html
    """
    join_the_movement = models.CharField(
        max_length=200,
        help_text="Large text directly before the call to action donation button at the bottom of the projects page, e.g. 'Join the movement.'",
        default="Join the movement."
    )

    start_funding_button_text = models.CharField(
        max_length=50,
        help_text="The label on the green call to action button at the bottom of the homepage.",
        default="Create a new project"
    )
    single_project_heading = models.CharField(
        max_length=50,
        help_text="The heading to display above the featured project on the projects list page when there is only one active project, e.g. 'Our current project'",
        default="OUR CURRENT PROJECT"
    )
    multiple_projects_heading = models.CharField(
        max_length=50,
        help_text="The heading to display above the featured project on the projects list when there are multiple active projects, e.g. 'Our current projects'",
        default="OUR CURRENT PROJECTS"
    )

@register_setting
class ShareThisSettings(BaseSetting):
    """
    ShareThis default Settings
    """
    image = models.URLField(verbose_name='Image Url', help_text='The Url of image that will be used in ShareThis widget')
    description = models.CharField(max_length=200, help_text="The description that will be used in ShareThis widget")


def main():
    with open('is_even.txt', 'w') as file:
        while True:
            a = get_int()
            if a:
                b = is_even(a)
                print(a, b, file=file)
            else:
                break

def get_int():
    num = input("Please, enter a number: ")
    try:
        return int(num)
    except ValueError:
        print("It's not a number!")
    else:
        return False

def is_even(n):
    if n % 2 == 0:
        return 'is even'
    return 'is odd'

if __name__ == "__main__":
    main()


lines = open('input.txt', 'r').readlines()
map = []
for line in lines:
    map.append(list(line.rstrip()))

dx = 3
dy = 1
x = y = 0
height = len(map)
width = len(map[0])
num_trees = 0

while y < height:
    c = map[y][(x % width)]
    if c == '#':
        num_trees += 1
    x += dx
    y += dy
print(num_trees)


import numpy as np

def perceptron(X, y):
    '''
    PERCEPTRON Perceptron Learning Algorithm.

       INPUT:  X: training sample features, P-by-N matrix.
               y: training sample labels, 1-by-N row vector.

       OUTPUT: w:    learned perceptron parameters, (P+1)-by-1 column vector.
               iter: number of iterations

    '''
    P, N = X.shape
    w = np.zeros((P + 1, 1))
    iters = 0
    X2 = np.vstack((np.ones((1, X.shape[1])), X))
    while(1):
        iters = iters + 1
        y2 = np.sign(np.matmul(w.T, X2))
        cnt = 0
        for i in range(y.shape[1]):
            if(y2[0, i] != y[0, i]):
                for j in range(len(w)):
                    w[j, 0] = w[j, 0] + X2[j, i] * y[0, i]
#                 w = w + X2 * y
                cnt = cnt + 1
        if(cnt == 0 or iters > 1000):
            break
    return w, iters


"""empty message

Revision ID: a128fdfc7118
Revises: 0fee365ecb9a
Create Date: 2023-04-11 17:57:44.260130

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = 'a128fdfc7118'
down_revision = '0fee365ecb9a'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('questionnaire_question', schema=None) as batch_op:
        batch_op.alter_column('content',
               existing_type=mysql.VARCHAR(length=255),
               type_=sa.Text(),
               existing_nullable=False)

    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    with op.batch_alter_table('questionnaire_question', schema=None) as batch_op:
        batch_op.alter_column('content',
               existing_type=sa.Text(),
               type_=mysql.VARCHAR(length=255),
               existing_nullable=False)

    # ### end Alembic commands ###


import sys
import heapq
import copy

input = sys.stdin.readline
INF = int(1e9)

# 다익스트라 함수
def dijkstra(start):
    dis = [INF] * (n + 1)  # 최소 비용 테이블
    dis[start] = 0  # 시작 지점 0 처리
    q = []
    heapq.heappush(q, (0, start))

    # 메인 로직
    while q:
        now_cost, now_way = heapq.heappop(q)

        if dis[now_way] < now_cost:
            continue

        # 최단 거리가 갱신되는 경우라면
        # 자기 자신을 통해 다른 곳으로 가는 지점의 경로 처리를 위해
        # 자기 자신 경로 테이블에 자기 자신 추가
        path[now_way].append(now_way)

        # 우선순위 큐에서 뽑은 것이 end와 일치하면 return
        if now_way == end:
            return dis[end]

        # 최단 거리 수정
        for new_cost, new_way in graph[now_way]:
            if dis[new_way] > new_cost + now_cost:
                dis[new_way] = new_cost + now_cost
                heapq.heappush(q, (dis[new_way], new_way))
                # 최단 거리 수정으로 인해 최단 경로 수정
                path[new_way] = copy.deepcopy(path[now_way])

n = int(input())
m = int(input())

graph = [[] for _ in range(n + 1)]  # 인접 리스트
path = [[] for _ in range(n + 1)]  # 경로 저장

# 그래프 정보
for _ in range(m):
    a, b, c = map(int, input().split())
    graph[a].append((c, b))

# 시작점 도착점
start, end = map(int, input().split())
print(dijkstra(start))  # 최소 비용 출력
print(len(path[end]))  # 경로 길이
print(*path[end])  # 경로 출력


import os
from libcity.data.dataset import TrafficStateDataset

class RoadNetWorkDataset(TrafficStateDataset):
    def __init__(self, config):
        self.config = config
        self.dataset = self.config.get('dataset', '')
        self.data_path = './raw_data/' + self.dataset + '/'
        self.geo_file = self.config.get('geo_file', self.dataset)
        self.rel_file = self.config.get('rel_file', self.dataset)
        assert os.path.exists(self.data_path + self.geo_file + '.geo')
        assert os.path.exists(self.data_path + self.rel_file + '.rel')
        super().__init__(config)

    def get_data(self):
        """
        返回数据的DataLoader，此类只负责返回路网结构adj_mx，而adj_mx在data_feature中，这里什么都不返回
        """
        return None, None, None

    def get_data_feature(self):
        """
        返回一个 dict，包含数据集的相关特征

        Returns:
            dict: 包含数据集的相关特征的字典
        """
        return {"adj_mx": self.adj_mx, "num_nodes": self.num_nodes,
                "geo_to_ind": self.geo_to_ind, "ind_to_geo": self.ind_to_geo}


import sys
import os
import errno
import argparse
import multiprocessing
import subprocess
from subprocess import Popen, PIPE
from cigar import Cigar
from datetime import datetime

def run(cmd, dieOnError=True):

	"""
	Runs a single subprocess in the background. Used to execute simple bash commands like cat *.txt

	run() was taken from Andy and modified:
	http://jura.wi.mit.edu/bio/education/hot_topics/python_pipelines_2014/python_pipelines_2014.pdf
	https://stackoverflow.com/questions/13398261/python-subprocess-call-and-subprocess-popen-stdout

	Args:
		cmd, the terminal command to run
		dieOnError, used to detect errors

	Returns:
	    (exitcode, stdout, stderr), tuple containing the results of the subprocess' execution

	Raises:
	    None
	"""

	ps = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
	exitcode = ps.returncode
	stdout,stderr = ps.communicate()
	return exitcode, stdout, stderr

def printJunctions(path, spliceDict,gene):
	"""
		spliceDict, a dictionary containing junctions and their read counts
			E.x. spliceDict[1:200-300] = 5
	"""
	for key in spliceDict:
		chrom, junctionStart, junctionEnd = key
		timesSeenInSample = str(spliceDict[key])

		with open(path, "a") as out:
			out.write("\t".join([str(chrom),str(junctionStart),str(junctionEnd),timesSeenInSample,gene])+"\n")

def parseCIGARForIntrons(cigar):

	"""
	Parses a CIGAR string and returns values which can used to determine an intron's
	3' and 5' splice sites

	Args:
		cigar, a CIGAR string with an intron in it
			E.x. cigar='3M1D40M20N'

	Returns:
	    offset, a figure which accomodates for insertion and deletion events to adjust
	    an alignment's positions back to the reference genome

	    matchedExon, a figure to be added to the start position of an alignment which
	    forms the 5' end of a splice site. This function only considers 'M''s before
	    an intron (N) for this figure.

		intronLength, the length of an intron as reported by the CIGAR string. This figure
		is added with matchedExon and the start of an alignment to produce the position of
		the 3' end of a splice site.

	Raises:
	    None
	"""

	if 'N' in cigar:
		cigar = cigar.split('N')[0] + 'N' #remove all information after intron
	else:
		raise Exception('No intron detected')

	offset = 0
	matchedExon = 0
	intronLength = 0

	for c in list(Cigar(cigar).items()): # returns list of tuples : [(20, 'N')]
		if c[1] == 'N':
			intronLength += int(c[0])
		elif c[1] == 'D':
			offset += int(c[0])
		elif c[1] == 'I':
			offset -= int(c[0])
		elif c[1] == 'M':
			matchedExon += int(c[0])
		## soft clipping is ignored
		## hard clipping is ignored too

	return offset, matchedExon, intronLength

def getJunctionsForAGene(bam,gene,chrom,start,end):
	"""
	Produces a file containing junction
	positions and their read counts for each gene:
		E.x. NPHS1.txt
			1	200	300	5
			1	344	355	2
	"""
	pos = ''.join([chrom, ':', start, '-', end])

	spliceDict = {}
	geneFilePath = (bam + ".junctions.txt")

	try:
		exitcode, stdout, stderr = run(' '.join(['samtools view', bam, pos]))
	except Exception as e:
		print ('Exception message: ' + str(e))
		print ("Exception occured while running \"samtools view\" on " + bam + " for position " + pos + " Skipping.")

	for line in stdout.splitlines():
		elems = line.decode().split()

		alignmentStart = int(elems[3])
		cigar = str(elems[5])
		alignmentScore = int(elems[1])

		if 'N' not in cigar:  	#only get introns
			continue

		if (alignmentScore >= 256):  	#only primary alignments
			continue

		if not ((alignmentStart > int(start)) and (alignmentStart < int(end))):  	#check if alignment start is after known junction start but before known junction end
			continue

		try:
			offset, matchedExon, intronLength = parseCIGARForIntrons(cigar)
		except Exception as e:
			print ('Error message: ' + str(e))
			print ('Error trying to parse CIGAR string: ' + cigar +  ' with the bam file ' + bam +  ' and the position: ' + pos + ' Skipping.')
			continue

		junctionStart = alignmentStart + matchedExon + offset
		junctionEnd = junctionStart + intronLength

		# Beryl Cummings' Code, taken from makeUniqSpliceDict()
		# uniqueSplice = ':'.join([chrom, str(junctionStart), str(junctionEnd)])
		uniqueSplice = (chrom, str(junctionStart), str(junctionEnd))

		if uniqueSplice not in spliceDict:
			spliceDict[uniqueSplice] = 1
		else:
			spliceDict[uniqueSplice] += 1

	del stdout # saves ram in between samtool calls
	if spliceDict:
		printJunctions(geneFilePath,spliceDict,gene)
		del spliceDict

def getJunctions(genes, bam):
	with open(genes) as tf:
		for line in tf:
			elems = line.strip().split()
			chrom, start, end, gene = elems #edit the transcript file so that you only deal with junction coordinates
			getJunctionsForAGene(bam, gene, chrom, start, end)

if __name__=="__main__":
	print ('SpliceJunctionDiscover.py started on ' + datetime.now().strftime("%Y-%m-%d_%H:%M:%S.%f"))
	parser = argparse.ArgumentParser(description = 'Discover splice junctions in a bam file')
	parser.add_argument('-genes',help="A bed file of gene coordinates to discover junctions in",
						action='store',
			    		default = "/home/naumenko/crt/genes.bed")
	parser.add_argument('-bam',help='A bam file')
	args=parser.parse_args()

	getJunctions(args.genes, args.bam)

	# transcriptFile = str(args.transcriptFile).rsplit('/')[-1] #remove paths

	print ('SpliceJunctionDiscover.py finished on ' + datetime.now().strftime("%Y-%m-%d_%H:%M:%S.%f"))


"""empty message

Revision ID: aa697dcffdcb
Revises: aaa292210c15
Create Date: 2022-06-28 08:13:35.018528

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql

# revision identifiers, used by Alembic.
revision = 'aa697dcffdcb'
down_revision = 'aaa292210c15'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('favorites',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('item_id', sa.Integer(), nullable=False),
    sa.Column('item_name', sa.String(length=120), nullable=False),
    sa.Column('category', sa.String(length=120), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.drop_table('favorites_people')
    op.drop_table('favorites_planets')
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('favorites_planets',
    sa.Column('id', mysql.INTEGER(), autoincrement=True, nullable=False),
    sa.Column('user_id', mysql.INTEGER(), autoincrement=False, nullable=False),
    sa.Column('planets_id', mysql.INTEGER(), autoincrement=False, nullable=False),
    sa.ForeignKeyConstraint(['planets_id'], ['planets.id'], name='favorites_planets_ibfk_1'),
    sa.ForeignKeyConstraint(['user_id'], ['user.id'], name='favorites_planets_ibfk_2'),
    sa.PrimaryKeyConstraint('id'),
    mysql_collate='utf8mb4_0900_ai_ci',
    mysql_default_charset='utf8mb4',
    mysql_engine='InnoDB'
    )
    op.create_table('favorites_people',
    sa.Column('id', mysql.INTEGER(), autoincrement=True, nullable=False),
    sa.Column('user_id', mysql.INTEGER(), autoincrement=False, nullable=False),
    sa.Column('people_id', mysql.INTEGER(), autoincrement=False, nullable=False),
    sa.Column('people_name', mysql.VARCHAR(length=120), nullable=True),
    sa.ForeignKeyConstraint(['people_id'], ['people.id'], name='favorites_people_ibfk_1'),
    sa.ForeignKeyConstraint(['user_id'], ['user.id'], name='favorites_people_ibfk_2'),
    sa.PrimaryKeyConstraint('id'),
    mysql_collate='utf8mb4_0900_ai_ci',
    mysql_default_charset='utf8mb4',
    mysql_engine='InnoDB'
    )
    op.drop_table('favorites')
    # ### end Alembic commands ###


# coding: utf-8
from django.utils import six

from modernrpc.conf import settings

def generic_convert_string(v, from_type, to_type, encoding):
    """Generic method to convert from a unicode to str or from str to unicode. Works only with Python 2"""

    if from_type == str and isinstance(v, str):
        return unicode(v, encoding)

    elif from_type == unicode and isinstance(v, unicode):
        return v.encode(encoding)

    elif isinstance(v, (list, tuple, set)):
        return type(v)([generic_convert_string(element, from_type, to_type, encoding) for element in v])

    elif isinstance(v, dict):
        return {k: generic_convert_string(v, from_type, to_type, encoding) for k, v in v.iteritems()}

    return v

def standardize_strings(arg, strtype=settings.MODERNRPC_PY2_STR_TYPE, encoding=settings.MODERNRPC_PY2_STR_ENCODING):
    assert six.PY2, "This function should be used with Python 2 only"

    if not strtype:
        return arg

    if strtype == str or strtype == 'str':
        # We want to convert from unicode to str
        return generic_convert_string(arg, unicode, str, encoding)

    elif strtype == unicode or strtype == 'unicode':
        # We want to convert from str to unicode
        return generic_convert_string(arg, str, unicode, encoding)

    raise TypeError('standardize_strings() called with an invalid strtype: "{}"'.format(repr(strtype)))


import logging
logger = logging.getLogger(__name__)

from test.security.app import rest

from redbean.secure.identity import SessionIdentity

rest.set_path('../user')

@rest.get('{user_id}/hi')
@rest.guarded('a', 'b')
@rest.guarded('c')
async def hi(user_id: int) -> dict:
    return {"id": 222*1000 + user_id}

# @REST.GET('{user_id}/session')
async def get_user_session(user_id: int, identity) -> dict:
    return {"id": 100000}


import json

# ----------------
# IO utils
# ----------------

def load(path):
    with open(path) as file:
        data = json.load(file)
    return data

def save(path, output):
    with open(path, "w") as file:
        json.dump(output, file, indent=4)

# ----------------
# functional utils
# ----------------

def getCommissionInterval(objective, progress):
    """ returns the commission Interval given the 'objective' of the user and the 'progress' (amount of deals) he made so far.
            - 0.15 if (the progress is above his objective)                     --> 15% Interval
            - 0.1  if (the progress is between 50% and 100% of his objective)   --> 10% Interval
            - 0.05 if (the progress is between 0% and 50% of his objective)     --> 5% Interval

    Args:
        objective (float): the user's objective
        progress (float): the amount of deals he sold so far. (How far has he progressed towards his objective)

    Returns:
        float: the corresponding interval (0.05, 0.1 or 0.15)
    """
    if (progress > objective):
        p = 0.15
    elif (progress > (0.5 * objective)):
        p = 0.1
    else:
        p = 0.05
    return p

def twoSplitsCommission(threshold, progress, amount, currInterval, nextInterval):
    """ computes the commission of a deal, when the deal is split between two intervals.

    Args:
        threshold (float): threshold seperating the two intervals. It can be either (50% of the objective) or (the objective).
        progress (float): the cumulative sum of deals commissioned so far.
        amount (float): the amount of the current deal, that is being commissioned.
        currInterval (float): the Commissioning Interval reached so far (with 'progress')
        nextInterval (float): the Commissioning Interval to be reached after closing the current deal (with 'progress + amount')

    Returns:
        float: the commission associated to the deal.
    """
    amount1 = threshold - progress
    return amount1 * currInterval + (amount - amount1) * nextInterval

def computeCommission(objective, progress, amount):
    """ computes the commission of a deal given its amount, the user's objective and how far has he progressed towards his objective.

    Args:
        objective (float): the user's objective
        progress (float): the cumulative sum of deals commissioned so far.
        amount (float): the amount of the current deal, that is being commissioned.

    Raises:
        ValueError:

    Returns:
        float: the commission associated to the deal.
    """
    currInterval = getCommissionInterval(objective, progress)
    nextInterval = getCommissionInterval(objective, progress + amount)

    if (currInterval == nextInterval):
        # By closing this deal, the salesman will stay in the same interval of progress with respect to his objective.
        commission = amount * nextInterval

    elif (currInterval == 0.05 and nextInterval == 0.1):
        # The salesman will switch from the 5% interval to the 10% interval.
        # Therefore the deal is split into the two intervals from either side of the THRESHOLD = "50% of his objective"
        commission = twoSplitsCommission(0.5 * objective, progress, amount, currInterval, nextInterval)

    elif (currInterval == 0.1 and nextInterval == 0.15):
        # The salesman will switch from the 5% interval to the 10% interval.
        # Therefore the deal is split into the two intervals from either side of the THRESHOLD = "100% of his objective"
        commission = twoSplitsCommission(objective, progress, amount, currInterval, nextInterval)

    elif (currInterval == 0.05 and nextInterval == 0.15):
        # The salesman will switch from the 5% interval to the 15% interval.
        # Therefore the deal is split into the three intervals (5%, 10% and 15% interval)
        amount1 = 0.5 * objective - progress; # amount to reach 10% interval
        amount2 = 0.5 * objective; # amount to reach 15% interval
        amount3 = amount - (amount1 + amount2)
        commission = amount1 * 0.05 + amount2 * 0.1 + amount3 * 0.15

    else:
        raise ValueError
    return commission

# ----------------
# main loop
# ----------------

def main(inputPath, outputPath):
    """ main function

    Args:
        inputPath (string): path to the input data
        outputPath (string): path to the output file
    """
    # load data
    jsonData = load(inputPath)
    users = jsonData['users']
    deals = jsonData['deals']

    # initialize outputs and auxiliary variables
    outDeals = []
    outCommissions = []
    usersIds = []
    monthProgress = []
    for i in range(len(users)):
        id = users[i]['id']
        outCommissions.append({"user_id": id, "commission": {}})
        outDeals.append({"user_id": id, "deals": []})
        usersIds.append(id)
        monthProgress.append(0)

    # process deals
    for i in range(len(deals)):
        deal = deals[i]
        idx = usersIds.index(deal['user'])
        commissions = outCommissions[idx]['commission']
        objective = users[idx]['objective']
        amount = deal['amount']
        month = deal['payment_date'][:7]

        # compute the commission associated to the deal
        if (month in commissions):
            progress = monthProgress[idx]
            c0 = commissions[month]
        else:
            progress = 0
            c0 = 0
        c = computeCommission(objective, progress, amount)

        # update output and auxiliary variables
        outCommissions[idx]['commission'][month] = c0 + c
        outDeals[idx]['deals'].append({"id": deal['id'],"commission": c})
        monthProgress[idx] = progress + amount

    # sort deals (and their associated commissions) by users
    sortedDeals = []
    for i in range(len(outDeals)):
        sortedDeals.append(outDeals[i]['deals'])

    # save output
    output = {
        "commissions": outCommissions,
        "deals": sortedDeals
    }
    save(outputPath, output)

# ----------------
# test
# ----------------
if __name__ == "__main__":
    main('./data/input.json', 'output_py.json')


class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        '''
        hashmap + backtrack
            hashmap 维护每个数字对应的所有可能字母
            每次取电话号码的一位数字，获得该数字对应的所有可能的字母，将其中的一个字母插入到已有的字母排列后面
            直到处理完电话号码中的所有数字，即得到一个完整的字母排列
            然后进行回退操作，遍历其余的字母排列

        '''
        keyboard = {
            "2": "abc",
            "3": "def",
            "4": "ghi",
            "5": "jkl",
            "6": "mno",
            "7": "pqrs",
            "8": "tuv",
            "9": "wxyz"
        }
        res = []
        path = []

        if not digits:
            return []

        def backtrack(n):
            if n == len(digits):
                res.append(''.join(path))
            else:
                digit = digits[n]
                for letter in keyboard[digit]:
                    path.append(letter)
                    backtrack(n+1)
                    path.pop()
        backtrack(0)
        return res


"""Predicting Module."""

from collections import OrderedDict
from typing import List

import click
import numpy as np
import pandas as pd
from albumentations import Compose
from PIL import Image
from pytesseract import image_to_string
from skimage.filters import threshold_otsu
from skimage.segmentation import clear_border
from skimage.measure import label, regionprops
from skimage.morphology import closing, square, convex_hull_image
from skimage.transform import resize
from skimage.util import invert

from tablenet import TableNetModule

class Predict:
    """Predict images using pre-trained model."""

    def __init__(self, checkpoint_path: str, transforms: Compose, threshold: float = 0.5, per: float = 0.005):
        """Predict images using pre-trained TableNet model.

        Args:
            checkpoint_path (str): model weights path.
            transforms (Optional[Compose]): Compose object from albumentations used for pre-processing.
            threshold (float): threshold to consider the value as correctly classified.
            per (float): Minimum area for tables and columns to be considered.
        """
        self.transforms = transforms
        self.threshold = threshold
        self.per = per

        self.model = TableNetModule.load_from_checkpoint(checkpoint_path)
        self.model.eval()
        self.model.requires_grad_(False)

    def predict(self, image: Image) -> List[pd.DataFrame]:
        """Predict a image table values.

        Args:
            image (Image): PIL.Image to

        Returns (List[pd.DataFrame]): Tables in pandas DataFrame format.
        """
        processed_image = self.transforms(image=np.array(image))["image"]

        table_mask, column_mask = self.model.forward(processed_image.unsqueeze(0))

        table_mask = self._apply_threshold(table_mask)
        column_mask = self._apply_threshold(column_mask)

        segmented_tables = self._process_tables(self._segment_image(table_mask))

        tables = []
        for table in segmented_tables:
            segmented_columns = self._process_columns(self._segment_image(column_mask * table))
            if segmented_columns:
                cols = []
                for column in segmented_columns.values():
                    cols.append(self._column_to_dataframe(column, image))
                tables.append(pd.concat(cols, ignore_index=True, axis=1))
        return tables

    def _apply_threshold(self, mask):
        mask = mask.squeeze(0).squeeze(0).numpy() > self.threshold
        return mask.astype(int)

    def _process_tables(self, segmented_tables):
        width, height = segmented_tables.shape
        tables = []
        for i in np.unique(segmented_tables)[1:]:
            table = np.where(segmented_tables == i, 1, 0)
            if table.sum() > height * width * self.per:
                tables.append(convex_hull_image(table))

        return tables

    def _process_columns(self, segmented_columns):
        width, height = segmented_columns.shape
        cols = {}
        for j in np.unique(segmented_columns)[1:]:
            column = np.where(segmented_columns == j, 1, 0)
            column = column.astype(int)

            if column.sum() > width * height * self.per:
                position = regionprops(column)[0].centroid[1]
                cols[position] = column
        return OrderedDict(sorted(cols.items()))

    @staticmethod
    def _segment_image(image):
        thresh = threshold_otsu(image)
        bw = closing(image > thresh, square(2))
        cleared = clear_border(bw)
        label_image = label(cleared)
        return label_image

    @staticmethod
    def _column_to_dataframe(column, image):
        width, height = image.size
        column = resize(np.expand_dims(column, axis=2), (height, width), preserve_range=True) > 0.01

        crop = column * image
        white = np.ones(column.shape) * invert(column) * 255
        crop = crop + white
        ocr = image_to_string(Image.fromarray(crop.astype(np.uint8)))
        return pd.DataFrame({"col": [value for value in ocr.split("\n") if len(value) > 0]})

@click.command()
@click.option('--image_path', default="./data/Marmot_data/10.1.1.193.1812_24.bmp")
@click.option('--model_weights', default="./data/best_model.ckpt")
def predict(image_path: str, model_weights: str) -> List[pd.DataFrame]:
    """Predict table content.

    Args:
        image_path (str): image path.
        model_weights (str): model weights path.

    Returns (List[pd.DataFrame]): Tables in pandas DataFrame format.
    """
    import albumentations as album
    from albumentations.pytorch.transforms import ToTensorV2

    transforms = album.Compose([
        album.Resize(896, 896, always_apply=True),
        album.Normalize(),
        ToTensorV2()
    ])
    pred = Predict(model_weights, transforms)

    image = Image.open(image_path)
    print(pred.predict(image))

if __name__ == '__main__':
    predict()


import numpy as np
import glob
from nltk.tokenize import word_tokenize
import sys
import tweepy
import json
import time
import os

tweet_limit = 899

def retrieve_tweet(twt_prop_path, twt_ids, outfile='./tweets_jhu.json'):
    """
    Retrieve tweets
    :param twt_prop_path dictionary of twitter authentication info
    :param twt_ids: list of tweet ids
    :return:
    """
    twt_prop = dict() # Twitter auth properties
    try:
        twt_prop = json.load(open(twt_prop_path))
    except:
        print('Authentication file loading fail')
        sys.exit()

    auth = tweepy.OAuthHandler(twt_prop['api_key'], twt_prop['api_secret'])
    auth.set_access_token(twt_prop['access_token'], twt_prop['access_secret'])
    twt_api = tweepy.API(auth)

    global tweet_limit # the limit of request per 15 minutes
    """
        count and error_count record the number of tweets can be retrieved and unreachable

        The script supports continuous scraping through the finished_set and the finished_tmp file;
        If the id exists in the finished_tmp file, it will not be requested again.
    """
    finished_set = set()
    count = 0
    error_count = 0

    if os.path.isfile('./finished_tmp.txt'):
        finished_file = open('./finished_tmp.txt', 'a')
        with open('./finished_tmp.txt') as tmp_file:
            [finished_set.add(item.strip()) for item in tmp_file]
    else:
        finished_file = open('./finished_tmp.txt', 'w')

    if os.path.isfile(outfile):
        with open(outfile) as tmpfile:
            [finished_set.add(item.strip()) for item in tmpfile]
        writefile = open(outfile, 'a')
    else:
        writefile = open(outfile, 'w')

    for tid in twt_ids:
        if str(tid) in finished_set:
            continue

        try:
            #print('id'+str(tid))
            tweet = twt_api.get_status(tid)
            print(tweet)
            writefile.write(json.dumps(tweet._json)+'\n')
            finished_set.add(tid)
        except tweepy.TweepError as te:
            #print(te)
            error_count += 1
        finished_file.write(str(tid)+'\n')
        finished_set.add(str(tid))
        count += 1
        if count % 100 == 0:
            writefile.flush()
            finished_file.flush()

        if count >= tweet_limit:
            count -= tweet_limit
            time.sleep(60*15) # suspend for 15 minutes

    writefile.flush()
    writefile.close()
    os.remove('./finished_tmp.txt')

# scann the files within the current dir, the files contains Tweet IDs
work_dir = './'
save_dir = './'
if len(sys.argv) > 1:
    if os.path.exists(sys.argv[1]):
        work_dir = sys.argv[1]
    if os.path.exists(sys.argv[2]):
        save_dir = sys.argv[2]
    if not work_dir.endswith('/'):
        work_dir += '/'
    if not save_dir.endswith('/'):
        save_dir += '/'

files = glob.glob(work_dir + '*.txt') # you can also specify other directories
#print(files)
time.sleep(10)
for filepath in files:
    twids = open(filepath).readlines()
    twids = [item.split('\t')[0].strip() for item in twids]

    #print('Working on: ' + filepath)
    retrieve_tweet('./twitter.info', twids, outfile='./tweets_jhu.json')


"""Created on Sat Mar 18 09:00:12 2023.

@author: YuxiaoLan
"""

from HTMACat.catkit.gen.adsorption import Builder
from HTMACat.catkit.gratoms import *
from rdkit import Chem
from rdkit.Chem import AllChem, rdMolDescriptors
import math
from HTMACat.Extract_info import *
from HTMACat.model.Substrate import Slab
from HTMACat.catkit.gen.adsorption import AdsorptionSites
from HTMACat.model.Structure import Structure
import networkx.algorithms.isomorphism as iso
from ase import Atoms
from HTMACat.model.Species import init_from_ads, ABS_Species

class Adsorption(Structure):
    def __init__(self, species: list, sites: list, settings={}, spec_ads_stable=None, substrate=Slab()):
        if spec_ads_stable is None:
            spec_ads_stable = {
                "NH3": [1],
                "NH2": [2],
                "NH": [2, 4],
                "N": [2, 4],
                "O": [2, 4],
                "OH": [2, 4],
                "NO": [2, 4],
                "H2O": [1],
                "H": [2, 4],
            }
        assert isinstance(species, list), "species should be a list of Species class"
        assert isinstance(species[0], ABS_Species), "species should be a list of Species class"
        assert isinstance(sites, list), "sites should be a list"
        #assert sites[0] in ['1', '2'], 'Supports only "1" "2" adsorption sites type for ads!'
        self.species = species
        self.sites = sites
        self.spec_ads_stable = spec_ads_stable
        self.substrate = substrate
        self.settings = settings

    def set_species(self, species):
        self.species = species

    def add_species(self, species):
        self.species.append(species)

    def add_sites(self, sites):
        self.sites.append(sites)

    def get_sites(self):
        return self.sites # ' '.join(self.sites)

    def out_file_name(self):
        ads = []
        ads_str = self.species[0].out_file_name()
        substrate_str = self.substrate.out_file_name()
        vasp_file_str: str = "_".join([substrate_str, ads_str])
        return vasp_file_str

    def out_print(self):
        species_str = []
        for i in range(len(self.species)):
            species_str.append(self.species[i].out_print())

        species_str = " and ".join(species_str)
        substrate_str = self.substrate.out_print()
        print_str = f"{species_str} adsorption on {substrate_str}"
        return print_str

    def construct(self):
        if self.get_sites()[0] == '1':
            if len(self.get_sites()) == 1:
                slabs_ads = self.Construct_single_adsorption()
            else:
                ele = ''.join(self.get_sites()[1:]) ### wzj 20230518
                slabs_ads = self.Construct_single_adsorption(ele=ele)
        elif self.get_sites()[0] == '2':
            slabs_ads = self.Construct_double_adsorption()
        else:
            raise ValueError('Supports only "1" "2" adsorption sites for ads!')

        if self.substrate.is_dope():
            slabs_ads = self.remove_same(slabs_ads)

        return slabs_ads

    def remove_same(self, slabs_ads):
        # To choose the config whose neighbor list includes the doped atoms
        p1 = self.substrate.property["p1"]
        p1_symb = self.substrate.property["p1_symb"]
        slabs_ads_near = []
        for slb in slabs_ads:
            (
                bind_adatoms,
                bind_adatoms_symb,
                bind_type_symb,
                adspecie,
                bind_surfatoms,
                bind_surfatoms_symb,
            ) = get_binding_adatom(slb)
            if self.get_sites() == "1" and (set(p1_symb) & set(bind_surfatoms_symb[0])):
                slabs_ads_near += [slb]
            elif (
                self.get_sites() == "2"
                and (set(p1_symb) & set(bind_surfatoms_symb[0]))
                or (set(p1_symb) & set(bind_surfatoms_symb[0]))
            ):
                slabs_ads_near += [slb]
        return slabs_ads_near

    def vec_to_nearest_neighbor_site(self, slab, site_coords):
        # site_coords: a list containing 1 (ads) or 2 (coads) coord(s) of adsorption site(s)
        # return: the vector from the adsorption site of specie A to its nearest neighboring adsorption site
        # [The v_nn of specie A is always the v_nn of specie B too !!!]
        coord_images = site_coords
        num_origin_sites = len(coord_images)
        for d,dim in enumerate(slab._pbc):
            if dim:
                for i in range(num_origin_sites):
                    coord_images.append(coord_images[i]+slab._cellobj[d]) # coord_images[0]: the coord of specie A
                    coord_images.append(coord_images[i]-slab._cellobj[d])
        imagesites_distances = [np.sqrt(np.sum(np.square(v-coord_images[0]))) for v in coord_images]
        idx_tmp = np.argmin(imagesites_distances[1:]) + 1
        v_nn = coord_images[idx_tmp] - coord_images[0]
        #print('imagesites_distances--:', imagesites_distances, idx_tmp)
        #print('vec_to_neigh_imgsite--:', v_nn)
        return v_nn

    def dist_of_nearest_diff_neigh_site(self, slab, site_coords):
        # site_coords: a list of 2 site coords (different species)
        coord_images = site_coords
        num_origin_sites = len(coord_images)
        for d,dim in enumerate(slab._pbc):
            if dim:
                coord_images.append(coord_images[1]+slab._cellobj[d]) # coord_images[0]: the coord of specie A
                coord_images.append(coord_images[1]-slab._cellobj[d])
        imagesites_distances = [np.sqrt(np.sum(np.square(v[:2]-coord_images[0][:2]))) for v in coord_images]
        d = np.min(imagesites_distances[1:])
        return d

    def Construct_single_adsorption(self, ele=None):
        if 'direction' in self.settings.keys():
            _direction_mode = self.settings['direction']
        else:
            _direction_mode = 'bond_atom'
        if 'rotation' in self.settings.keys():
            _rotation_mode = self.settings['rotation']
        else:
            _rotation_mode = 'vnn'
        # generate surface adsorption configuration
        slab_ad = []
        slabs = self.substrate.construct()
        for i, slab in enumerate(slabs):
            site = AdsorptionSites(slab)
            coordinates = site.get_coordinates()
            builder = Builder(slab)
            ads_use, ads_use_charges = self.species[0].get_molecule()
            if not ele is None:
                if ele == '+':
                    bond_atom_ids = np.where(np.array(ads_use_charges)>0)[0]
                elif ele == '-':
                    bond_atom_ids = np.where(np.array(ads_use_charges)<0)[0]
                else:
                    chemical_symbols = np.array(ads_use.get_chemical_symbols())
                    bond_atom_ids = np.where(chemical_symbols==ele)[0]
                for j, coord in enumerate(coordinates):
                    vec_to_neigh_imgsite = self.vec_to_nearest_neighbor_site(slab=slab, site_coords=[coord])
                    for bond_id in bond_atom_ids:
                        slab_ad += [builder._single_adsorption(ads_use, bond=bond_id, site_index=j,
                                                               rotation_mode =_rotation_mode,
                                                               rotation_args ={'vec_to_neigh_imgsite':vec_to_neigh_imgsite},
                                                               direction_mode=_direction_mode)]
                        #if len(bond_atom_ids) > 1:
                        #    slab_ad += [builder._single_adsorption(ads_use, bond=bond_id, site_index=j, direction_mode='decision_boundary', direction_args=bond_atom_ids)]
            else:
                for j, coord in enumerate(coordinates):
                    vec_to_neigh_imgsite = self.vec_to_nearest_neighbor_site(slab=slab, site_coords=[coord])
                    slab_ad += [builder._single_adsorption(ads_use, bond=0, site_index=j,
                                                           rotation_mode =_rotation_mode,
                                                           rotation_args ={'vec_to_neigh_imgsite':vec_to_neigh_imgsite})]
        return slab_ad

    def Construct_double_adsorption(self):
        slab_ad = []
        slabs = self.substrate.construct()
        for i, slab in enumerate(slabs):
            site = AdsorptionSites(slab)
            builder = Builder(slab)
            ads_use, ads_use_charges = self.species[0].get_molecule()
            edges = site.get_adsorption_edges()
            for j, edge01 in enumerate(edges):
                slab_ad += [builder._double_adsorption(ads_use, bonds=[0, 1], edge_index=j)]
        return slab_ad

    @classmethod
    def from_input(cls, init_list, substrates, species_dict=None):
        ads = []
        for i in init_list:
            spec1 = init_from_ads(i[0], species_dict)
            sites1 = str(i[1])
            if len(i) > 2:
                settings1 = i[2]
                # print('settings1', settings1, '\n', settings1['settings'])
                for j in substrates:
                    ads.append(cls([spec1], list(sites1), settings=settings1['settings'], substrate=j))
            else:
                for j in substrates:
                    ads.append(cls([spec1], list(sites1), substrate=j))
        return ads

class Coadsorption(Adsorption):
    def __init__(self, species: list, sites: list, settings={}, spec_ads_stable=None, substrate=Slab()):
        super().__init__(species, sites, settings, spec_ads_stable, substrate)
        assert len(species) == 2, "Coads need Two adsorption Species, but %d was given" % len(
            species
        )

    def construct(self):
        ### Change by RxChen, 2023 7 26: ZhaojieWang 20230828:
        if ([self.get_sites()[0][0], self.get_sites()[1][0]] == ['1','1']):
            ele = [''.join(self.get_sites()[0][1:]),''.join(self.get_sites()[1][1:])]
            slabs_ads = self.Construct_coadsorption_11(ele=ele)
        elif ([self.get_sites()[0][0], self.get_sites()[1][0]] == ['1','2']):
            slabs_ads = self.Construct_coadsorption_12()
        elif ([self.get_sites()[0][0], self.get_sites()[1][0]] == ['2','2']):
            slabs_ads = self.Construct_coadsorption_22()
        else:
            raise ValueError("Supports only '1' or '2' adsorption sites for coads!")### end
        if self.substrate.is_dope():
            slabs_ads = self.remove_same(slabs_ads)
        return slabs_ads

    def out_file_name(self):
        ads = []
        for every_species in self.species:
            ads.append(every_species.out_file_name())
        ads_str = "_".join(ads)
        substrate_str = self.substrate.out_file_name()
        vasp_file_str = "_".join([substrate_str, ads_str])
        return vasp_file_str

    def remove_same(self, slabs_ads):
        # To choose the config whose neighbor list includes the doped atoms
        p1 = self.substrate.property["p1"]
        p1_symb = self.substrate.property["p1_symb"]
        slabs_ads_near = []
        for slb in slabs_ads:
            (
                bind_adatoms,
                bind_adatoms_symb,
                bind_type_symb,
                adspecie,
                bind_surfatoms,
                bind_surfatoms_symb,
            ) = get_binding_adatom(slb)
            bind_surfatoms_symb_all = sum(bind_surfatoms_symb, [])
            if set(p1_symb) & set(bind_surfatoms_symb_all):
                slabs_ads_near += [slb]
        return slabs_ads_near

    def Construct_coadsorption_11(self, ele=['','']):
        if 'direction' in self.settings.keys():
            _direction_mode = self.settings['direction']
        else:
            _direction_mode = 'bond_atom'
        if 'rotation' in self.settings.keys():
            _rotation_mode = self.settings['rotation']
        else:
            _rotation_mode = 'vnn'
        if 'site_locate_ads1' in self.settings.keys():
            _site_locate_ads1 = self.settings['site_locate_ads1']
        else:
            _site_locate_ads1 = None
        # # #
        slab_ad = []
        ads_type = self.spec_ads_stable
        dis_inter = self.substrate.get_dis_inter()
        slabs = self.substrate.construct()
        if 'coads_dist' in self.settings.keys():
            _dist_xoy_range = self.settings['coads_dist']
        else:
            la = np.sqrt(np.dot(slabs[0]._cellobj[0], slabs[0]._cellobj[0]))
            lb = np.sqrt(np.dot(slabs[0]._cellobj[1], slabs[0]._cellobj[1]))
            _dist_xoy_range = [min(0.4*min(la,lb), 4.0), 0.5*min(la,lb)]
        # generate surface adsorption configuration
        ads1_use, ads1_use_charges = self.species[0].get_molecule()
        ads2_use, ads2_use_charges = self.species[1].get_molecule()
        bond_atom_ids_list = [[],[]]
        if not ele[0] in ['', '+', '-']:
            chemical_symbols01 = np.array(ads1_use.get_chemical_symbols())
            bond_atom_ids_list[0] = np.where(chemical_symbols01==ele[0])[0]
        elif '+' == ele[0]:
            bond_atom_ids_list[0] = np.where(np.array(ads1_use_charges)>0)[0]
        elif '-' == ele[0]:
            bond_atom_ids_list[0] = np.where(np.array(ads1_use_charges)<0)[0]
        else:
            bond_atom_ids_list[0] = np.array([0])
        if not ele[1] in ['', '+', '-']:
            chemical_symbols02 = np.array(ads2_use.get_chemical_symbols())
            bond_atom_ids_list[1] = np.where(chemical_symbols02==ele[1])[0]
        elif '+' == ele[1]:
            bond_atom_ids_list[1] = np.where(np.array(ads2_use_charges)>0)[0]
        elif '-' == ele[1]:
            bond_atom_ids_list[1] = np.where(np.array(ads2_use_charges)<0)[0]
        else:
            bond_atom_ids_list[1] = np.array([0])
        for i, slab in enumerate(slabs):
            builder_01 = Builder(slab)
            sites_01 = AdsorptionSites(slab)
            sites_01_sym = sites_01.get_symmetric_sites()
            ###
            for bond_id01 in bond_atom_ids_list[0]:
                for bond_id02 in bond_atom_ids_list[1]:
                    for k, site_01_sym in enumerate(sites_01_sym):
                        coord_01 = sites_01.get_coordinates()[k]
                        # 暂不能确定vec_to_neigh_imgsite，必须先明确ads2_use所在位点，故此处暂生成slab_tmp用以给出ads2_use的可能位点
                        slab_tmp = builder_01._single_adsorption(ads1_use, bond=bond_id01, site_index=k, auto_construct=True, enable_rotate_xoy=False)
                        builder_tmp = Builder(slab_tmp)
                        sites_02 = AdsorptionSites(slab_tmp)
                        sites_02_sym = sites_02.get_symmetric_sites() # 得到的并不是通过get_coordinates()得到的位点坐标list中的下标，是与connectivity属性有关的编号（？）
                        for j, site_02_sym in enumerate(sites_02_sym):
                            coord_02 = builder_tmp.get_coordinates()[j]
                            vec_to_neigh_imgsite = self.vec_to_nearest_neighbor_site(slab=slab, site_coords=[coord_01,coord_02])
                            # print('vec_to_neigh_imgsite =', vec_to_neigh_imgsite)
                            slab_01 = builder_01._single_adsorption(ads1_use, bond=bond_id01, site_index=k, auto_construct=True,
                                                                   enable_rotate_xoy=True,
                                                                   rotation_mode =_rotation_mode,
                                                                   rotation_args ={'vec_to_neigh_imgsite':vec_to_neigh_imgsite},
                                                                   direction_mode=_direction_mode)
                            dis = np.linalg.norm(coord_01 - coord_02)
                            dis_xoy = self.dist_of_nearest_diff_neigh_site(slab_01, [coord_01,coord_02])
                            if dis < float(dis_inter[0]): # jqyang
                                continue
                            elif dis > float(dis_inter[1]): # jqyang
                                continue
                            elif (dis_xoy < _dist_xoy_range[0]) or (dis_xoy > _dist_xoy_range[1]): # zjwang 两吸附位点的距离条件（在xoy平面内）
                                continue
                            else:
                                builder_02 = Builder(slab_01)
                                idx = np.where(builder_02.get_symmetric_sites()==site_02_sym)[0] # zjwang
                                if len(idx) == 0:
                                    continue
                                slab_ = builder_02._single_adsorption(ads2_use, bond=bond_id02, site_index=idx[0], auto_construct=True, # site_index=j错误！！！
                                                                      enable_rotate_xoy=True,
                                                                      rotation_mode ='vertical to vec_to_neigh_imgsite',
                                                                      rotation_args ={'vec_to_neigh_imgsite':vec_to_neigh_imgsite},
                                                                      direction_mode=_direction_mode)
                                # 【slab_的构建中，site_index参数不得直接使用循环变量j】
                                # 因为对于对称吸附物种而言，某些旋转角度可能提高slab_01的对称性（相对于没有旋转操作的slab_tmp而言），使得builder_02.get_symmetric_sites()缩短
                                # （少数情况，例如两个Cl[Al]Cl共吸附且放开位点距离限制就存在此问题，可能报错下标溢出，即使不报也是错的，而两个非对称的Cl[Al]CC吸附就没有此问题）
                                # 已解决：由于缩短后的列表builder_02.get_symmetric_sites()是sites_02_sym的子集，直接找元素在builder_02.get_symmetric_sites()中的新下标（即idx[0]）作为site_index参数，没有则说明被其他对称位点覆盖，跳过
                                slab_ad += [slab_]
            ###
            '''
            for k, coord01 in enumerate(coordinates01):
                slab_tmp = builder01._single_adsorption(ads1_use, bond=0, site_index=k, auto_construct=True,
                                                        enable_rotate_xoy=False,
                                                        direction_mode='decision_boundary') # 此处bond参数随意，有吸附即可
                site02 = AdsorptionSites(slab_tmp)
                coordinates02 = site02.get_coordinates()
                print('len(coordinates01) =', len(coordinates01), len(site01.get_symmetric_sites()))
                print('len(coordinates02) =', len(coordinates02), len(site02.get_symmetric_sites()))
                ###print('len(coordinates01), len(coordinates02) =', len(coordinates01), len(coordinates02))
                # 第一个物种放到表面上之后打破了对称性才使得第二个物种的可吸附位点情况变多
                for j, coord02 in enumerate(coordinates02):
                    vec_to_neigh_imgsite = self.vec_to_nearest_neighbor_site(slab=slab, site_coords=[coord01,coord02])
                    dis = np.linalg.norm(coord01 - coord02)
                    dis_xoy = self.dist_of_nearest_diff_neigh_site(slab_tmp, [coord01,coord02])
                    if 0 and dis < float(dis_inter[0]):
                        continue
                    elif 0 and dis > float(dis_inter[1]):
                        continue
                    elif 0 and dis_xoy < dist_min_xoy: # 控制两吸附位点的距离（在xoy平面内）不能过小
                        continue
                    else:
                        # 确定最近邻位点连线后正式构建前一个物种的吸附表面
                        for bond_id01 in bond_atom_ids_list[0]:
                            for bond_id02 in bond_atom_ids_list[1]:
                                slab_pre = builder01._single_adsorption(ads1_use, bond=bond_id01, site_index=k, auto_construct=True,
                                                                    enable_rotate_xoy=True,
                                                                    rotation_mode ='vertical to vec_to_neigh_imgsite',
                                                                    rotation_args ={'vec_to_neigh_imgsite':vec_to_neigh_imgsite},
                                                                    direction_mode='decision_boundary')
                                builder02 = Builder(slab_pre)
                                print('>>> >>> >>>', len(builder02.get_symmetric_sites()), len(builder02.get_periodic_sites()))
                                k_verbose = [False,False,True]
                                if k_verbose[k]:
                                    print('********** k, j, coordinates02[j] (j is site_index):\n', k, j, coordinates02[j])
                                slab_ = builder02._single_adsorption(
                                            ads2_use, bond=bond_id02, site_index=j, auto_construct=True,
                                            enable_rotate_xoy=True,
                                            rotation_mode ='vertical to vec_to_neigh_imgsite',
                                            rotation_args ={'vec_to_neigh_imgsite':vec_to_neigh_imgsite},
                                            direction_mode='decision_boundary',
                                            verbose=k_verbose[k]
                                        )
                                slab_ad += [slab_]
            '''

        typ = {None: 0, "top": 1, "bri": 2, "fcc": 3, "hcp": 3, "4-fold": 4}
        # view(slab_ad)
        slab_ad_final = []
        for j, adslab in enumerate(slab_ad):
            (
                bind_adatoms,
                bind_adatoms_symb,
                adspecie,
                bind_type_symb,
                bind_surfatoms,
                bind_surfatoms_symb,
            ) = get_binding_adatom(adslab)
            adspecie_tmp, bind_type_symb_tmp = [], []
            for k, spe in enumerate(adspecie):
                if spe in ads_type.keys():
                    adspecie_tmp += [spe]
                    bind_type_symb_tmp += [bind_type_symb[k]]
            if len(adspecie_tmp) < 2:
                # print('Can not identify the config!')
                slab_ad_final += [adslab]
            elif typ.get(bind_type_symb_tmp[0]) in ads_type.get(adspecie_tmp[0]) and \
                 typ.get(bind_type_symb_tmp[1]) in ads_type.get(adspecie_tmp[1]):
                slab_ad_final += [adslab]
        return slab_ad_final

    def Construct_coadsorption_12(self):
        slab_ad = []
        slabs = self.substrate.construct()
        dis_inter = self.substrate.get_dis_inter()
        for i, slab in enumerate(slabs):
            site01 = AdsorptionSites(slab)
            # print(site01.get_symmetric_sites())
            builder01 = Builder(slab)
            coordinate01 = site01.get_coordinates()
            # generate surface adsorption configuration
            ads1_use, ads1_use_charges = self.species[0].get_molecule()
            ads2_use, ads2_use_charges = self.species[1].get_molecule()
            for k, coord01 in enumerate(coordinate01):
                slab = builder01._single_adsorption(ads1_use, bond=0, site_index=k)
                # after adsorbing an atoms
                # site analysis and surface builder
                site02 = AdsorptionSites(slab)
                builder02 = Builder(slab)
                # obtain the edges and ID and coordinates of all sites
                edge02 = site02.get_adsorption_edges()
                site_coord02 = site02.get_coordinates(unique=False)
                site_type02 = site02.get_periodic_sites(screen=True)
                dic_site = {}
                keys = [site_type02[i] for i in range(len(site_type02))]
                values = [site_coord02[i] for i in range(len(site_type02))]
                dic_site = dict(zip(keys, values))
                # emiliate the too near site
                for j, edge in enumerate(edge02):
                    coord10 = dic_site.get(edge[0])
                    coord11 = dic_site.get(edge[1])
                    if coord10 is not None:
                        dis1 = np.linalg.norm(coord01 - coord10)
                    else:
                        dis1 = dis_inter[0] + 0.1
                    if coord11 is not None:
                        dis2 = np.linalg.norm(coord01 - coord11)
                    else:
                        dis2 = dis_inter[1] + 0.1
                    dis = min(dis1, dis2)

                    if dis < dis_inter[0]:
                        continue
                    elif dis > dis_inter[1]:
                        continue
                    else:
                        slab_ad += [
                            builder02._double_adsorption(ads2_use, bonds=[0, 1], edge_index=j)
                        ]
        return slab_ad

    def Construct_coadsorption_22(self):
        slab_ad = []
        dis_inter = self.substrate.get_dis_inter()
        slabs = self.substrate.construct()
        for i, slab in enumerate(slabs):
            site01 = AdsorptionSites(slab)
            # print(site01.get_symmetric_sites())
            builder01 = Builder(slab)
            # coordinate01 = site01.get_coordinates()
            edge01 = site01.get_adsorption_edges()
            site_coord01 = site01.get_coordinates(unique=False)
            site_type01 = site01.get_periodic_sites(screen=True)
            dic_site01 = {}
            keys = [site_type01[i] for i in range(len(site_type01))]
            values = [site_coord01[i] for i in range(len(site_type01))]
            dic_site01 = dict(zip(keys, values))
            # generate surface adsorption configuration
            ads1_use, ads1_use_charges = self.species[0].get_molecule()
            ads2_use, ads2_use_charges = self.species[1].get_molecule()
            for k, edge01 in enumerate(edge01):
                slab = builder01._double_adsorption(ads1_use, bonds=[0, 1], edge_index=k)
                coord00 = dic_site01.get(edge01[0])
                coord01 = dic_site01.get(edge01[1])
                ## after adsorbing an atoms
                # site analysis and surface builder
                site02 = AdsorptionSites(slab)
                builder02 = Builder(slab)
                # obtain the edges and ID and coordinates of all sites
                edge02 = site02.get_adsorption_edges()
                site_coord02 = site02.get_coordinates(unique=False)
                site_type02 = site02.get_periodic_sites(screen=True)
                dic_site02 = {}
                keys = [site_type02[i] for i in range(len(site_type02))]
                values = [site_coord02[i] for i in range(len(site_type02))]
                dic_site02 = dict(zip(keys, values))
                ## emiliate the too near site
                for j, edge in enumerate(edge02):
                    coord10 = dic_site02.get(edge[0])
                    coord11 = dic_site02.get(edge[1])
                    if not coord10 is None:
                        dis1 = np.linalg.norm(coord01 - coord10)
                    else:
                        dis1 = dis_inter[0] + 0.1
                    if not coord11 is None:
                        dis2 = math.hypot(
                            coord00[0] - coord11[0],
                            coord00[1] - coord11[1],
                            coord00[2] - coord11[2],
                        )
                    else:
                        dis2 = dis_inter[1] + 0.1
                    dis = min(dis1, dis2)

                    if dis < dis_inter[0]:
                        continue
                    elif dis > dis_inter[1]:
                        continue
                    else:
                        slab_ad += [
                            builder02._double_adsorption(ads2_use, bonds=[0, 1], edge_index=j)
                        ]
        return slab_ad

    @classmethod
    def from_input(cls, init_list, substrates, species_dict=None):
        ads = []
        for i in init_list:
            spec1 = init_from_ads(i[0], species_dict)
            spec2 = init_from_ads(i[1], species_dict)
            sites1 = str(i[2])
            sites2 = str(i[3])
            if len(i) > 4:
                settings1 = i[4]
                # print('settings1', settings1, '\n', settings1['settings'])
                for j in substrates:
                    ads.append(cls([spec1, spec2], [sites1, sites2], settings=settings1['settings'], substrate=j))
            else:
                for j in substrates:
                    ads.append(cls([spec1, spec2], [sites1, sites2], substrate=j))
        return ads

def ads_from_input(ads_model, substrate, species_dict=None):
    ads = []
    new_ads = []
    ads_type_list = ["ads", "coads"]
    for key, value in ads_model.items():
        if key == "coads":
            new_ads = Coadsorption.from_input(value, substrate, species_dict)
        elif key == "ads":
            new_ads = Adsorption.from_input(value, substrate, species_dict)
        else:
            msg = ",".join(ads_type_list)
            warn_msg = (
                "Only support species type: %s, Your input %s part in Species will be dismiss"
                % (msg, key)
            )
            raise Warning(warn_msg)
        ads = ads + new_ads
    return ads


from utils import *

# path_ = "C:/Users/benya/Desktop/my_PhD/QQE/codes/4_results/9_synthetic_separationOfClasses/"
# n_classes = 3

path_ = "C:/Users/benya/Desktop/my_PhD/QQE/codes/4_results/17_face_glasses_transform_inputSpace/run2_good/"
n_classes = 2

time_matching_list = []
time_quasi_newton_list = []
for class_index in range(n_classes):
    # print("class_index: " + str(class_index))
    path_file = path_ + "algorithm_files/class_" + str(class_index) + "/matched_data/"
    time_matching = load_variable(name_of_variable="time_matching", path=path_file)
    time_matching_list.append(time_matching)
    path_file = path_ + "algorithm_files/class_" + str(class_index) + "/fuzzy_QQplot/"
    time_quasi_newton = load_variable(name_of_variable="time_quasi_newton", path=path_file)
    time_quasi_newton_list.append(time_quasi_newton[-1])
total_time = sum(time_matching_list) + sum(time_quasi_newton_list)
print(total_time)


from datetime import datetime
from airflow import DAG
from airflow.operators.dummy import DummyOperator

def get_sub_dag(parent_dag_name, child_dag_name):
    dag_subdag = DAG(
        dag_id=f'{parent_dag_name}.{child_dag_name}',
        start_date=datetime(2021, 1, 1),
        catchup=False,
        schedule_interval="@once",
    )
    for i in range(5):
        DummyOperator(
            task_id=f'{child_dag_name}-task-{i + 1}',
            dag=dag_subdag,
        )
    return dag_subdag


# -*- coding: utf-8 -*-
"""
Created on Tue Dec  8 11:32:21 2020

@author: s1430
"""

import numpy as np

a = np.array([0, 1, 2])
print(np.tile(a, 2))
print(np.tile(a, (3, 2)))
print(np.tile(a, (2, 3, 4)))

b = np.arange(6).reshape(2, 3)
print(np.tile(b, 2))

print(np.tile(b, (2, 3)))
print(np.tile(b, (2, 1, 1)))

a = np.arange(10000).reshape(-1, 1)
b = np.arange(10000).reshape(1, -1)
print(a * b)

a = np.arange(10000).reshape(-1, 1)
b = np.arange(10000)

import time
time1 = time.time()
a * b
time1 = time.time() - time1
time2 = time.time()
np.tile(a, (1, 10000)) * np.tile(b, (10000, 1))
time2 = time.time() - time2
print(time1, time2)

c = np.random.rand(10)
b = np.array([0, 1, 0, 2, 1])
b = np.tile(b, 2)
print(c * b)


import cStringIO
import json
import logging
import optparse
import os
import shutil
import subprocess
import urllib
import urllib2
import zipfile

_LOGGER = logging.getLogger(os.path.basename(__file__))

_SRC_DIR = os.path.abspath(
    os.path.join(os.path.dirname(__file__), '../..'))
_VERSION_FILE = os.path.join(_SRC_DIR, 'syzygy/VERSION')
_BINARIES_DIR = os.path.join(_SRC_DIR, 'syzygy/binaries')
_EXE_DIR = os.path.join(_BINARIES_DIR, 'exe')

_SYZYGY_WATERFALL_URL = 'http://build.chromium.org/p/client.syzygy'
_SYZYGY_OFFICIAL = 'Syzygy Official'

_SYZYGY_ARCHIVE_URL = ('http://syzygy-archive.commondatastorage.googleapis.com/'
    'builds/official/%(revision)d')

def _Shell(*cmd, **kw):
  """Runs cmd, returns the results from Popen(cmd).communicate()."""
  _LOGGER.info('Executing %s.', cmd)
  prog = subprocess.Popen(cmd, shell=True, **kw)

  stdout, stderr = prog.communicate()
  if prog.returncode != 0:
    raise RuntimeError('Command "%s" returned %d.' % (cmd, prog.returncode))
  return (stdout, stderr)

def _Download(url):
  """Downloads the given URL and returns the contents as a string."""
  response = urllib2.urlopen(url)
  if response.code != 200:
    raise RuntimeError('Failed to download "%s".' % url)
  return response.read()

def _QueryWaterfall(path):
  """Queries the JSON API of the Syzygy waterfall."""
  url = _SYZYGY_WATERFALL_URL + '/json' + path
  data = _Download(url)
  return json.loads(data)

def _GetLastOfficialBuildRevision():
  """Query the Syzygy waterfall to get the SVN revision associated with the
  last successful official build.
  """
  # First make sure the builder doesn't have any pending builds and is idle.
  builders = _QueryWaterfall('/builders')
  if builders[_SYZYGY_OFFICIAL]['pendingBuilds'] > 0:
    raise RuntimeError('There are pending official builds.')
  if builders[_SYZYGY_OFFICIAL]['state'] != 'idle':
    raise RuntimeError('An official build is in progress.')

  # Get the information from the last build and make sure it passed before
  # extracting the revision number.
  build = _QueryWaterfall('/builders/%s/builds/-1' %
      urllib.quote(_SYZYGY_OFFICIAL))
  if 'successful' not in build['text']:
    raise RuntimeError('Last official build failed.')
  return int(build['sourceStamp']['revision'])

def main():
  option_parser = optparse.OptionParser()
  option_parser.add_option(
      '--revision', type="int",
      help='The SVN revision associated with the release build. '
           'If omitted, the SVN revision of the last successful official '
           'build will be used.')
  options, args = option_parser.parse_args()
  if args:
    option_parser.error('Unexpected arguments: %s' % args)

  # Enable info logging.
  logging.basicConfig(level=logging.INFO)

  # Get the SVN revision associated with the archived binaries to use.
  if options.revision is not None:
    revision = options.revision
  else:
    revision = _GetLastOfficialBuildRevision()
    _LOGGER.info('Using official build at revision %d.' % revision)

  # And build the corresponding archive URL.
  archive_url = _SYZYGY_ARCHIVE_URL % { 'revision': revision }
  benchmark_url = archive_url + '/benchmark.zip'
  binaries_url = archive_url + '/binaries.zip'

  # Download the archives.
  _LOGGER.info('Retrieving benchmark archive at "%s".', benchmark_url)
  benchmark_data = _Download(benchmark_url)
  _LOGGER.info('Retrieving binaries archive at "%s".', binaries_url)
  binaries_data = _Download(binaries_url)

  # Create a new feature branch off the master branch for the release
  # before we start changing any files.
  _LOGGER.info('Creating a release-binaries feature branch.')
  _Shell('git', 'checkout', '-b', 'release-binaries', 'master')

  # Clean out the output directories.
  shutil.rmtree(_BINARIES_DIR, True)
  os.makedirs(_BINARIES_DIR)
  os.makedirs(_EXE_DIR)

  # Extract the contents of the benchmark archive to the binaries directory.
  _LOGGER.info('Unzipping benchmark archive.')
  archive = zipfile.ZipFile(cStringIO.StringIO(benchmark_data))
  archive.extractall(_BINARIES_DIR)

  # Extract the binaries archives to the exe directory.
  _LOGGER.info('Unzipping binaries archive.')
  archive = zipfile.ZipFile(cStringIO.StringIO(binaries_data))
  archive.extractall(_EXE_DIR)

  # Add all the new files to the repo.
  _LOGGER.info('Committing release files.')
  # Update any changed or deleted files.
  _Shell('git', 'add', '-u', _BINARIES_DIR)
  # Add new files.
  _Shell('git', 'add', _BINARIES_DIR)

  # Now commit and upload the new binaries.
  message = 'Checking in version %d release binaries.' % revision
  _Shell('git', 'commit', '-m', message)
  _Shell('git', 'cl', 'upload', '-t', message)

if __name__ == '__main__':
  main()


#!/usr/bin/python
# -*- coding: UTF-8 -*-

import unittest

import ew_kw
import oh_kw
import od_kw
import es_kw

MojeSlupki = es_kw.MojeSlupki

class FakturoweMiesieczneSlupki(MojeSlupki):
    def __init__(self, tgk, aqr, dnw, rn_after):
        '''
        FakturoweMiesieczneSlupki:
        '''
        MojeSlupki.__init__(self, tgk, aqr, dnw, rn_after)

    def ustaw_skalowanie_obrazu(self):
        '''
        FakturoweMiesieczneSlupki:
        '''
        self.ustaw_prosty_obraz()

    def wyznacz_etykiete(self, pocz):
        '''
        FakturoweMiesieczneSlupki:
        '''
        return ''

class TestFakturowychMiesiecznychSlupkow(unittest.TestCase):
    def test_fakturowych_miesiecznych_slupkow(self):
        '''
        TestFakturowychMiesiecznychSlupkow:
        '''
        tgk = od_kw.PseudoTGK()
        tgk.wyznacz_unikalny_moment_dla_grafiki()
        aqr = ew_kw.SzkieletDatDlaFakturMiesLat()
        aqr.przypisz_dla_roku_szkielet(2012, rok_z_rozszerzeniem=0)
        lp_wykresu = 0
        dnw = oh_kw.SimpleDNW(lp_wykresu)
        rn_after = 2
        obk = FakturoweMiesieczneSlupki(tgk, aqr, dnw, rn_after)
        self.assertEqual(obk.szerokosc_dx_skali, 0)
        self.assertEqual(obk.szerokosc_slupka, 30)
        self.assertEqual(obk.wysokosc_obrazu, 150)
        self.assertEqual(obk.margines_dy_powyzej_slupka, 20)
        self.assertEqual(obk.wsp_y_na_dole_slupka, 130)
        self.assertEqual(obk.gorna_mniejsza, 140)
        self.assertEqual(obk.chce_bez_tresci, 0)


# parameters and paths
from simple_dqn_agent import SimpleDQNAgent
from anon_env import AnonEnv

DIC_EXP_CONF = {
    "RUN_COUNTS": 3600,
    "TRAFFIC_FILE": [
        "cross.2phases_rou01_equal_450.xml"
    ],
    "MODEL_NAME": "SimpleDQN",
    "NUM_ROUNDS": 200,
    "NUM_GENERATORS": 3,
    "LIST_MODEL":
        ["SimpleDQN"],
    "LIST_MODEL_NEED_TO_UPDATE":
        ["SimpleDQN"],
    "MODEL_POOL": False,
    "NUM_BEST_MODEL": 3,
    "PRETRAIN": True,
    "PRETRAIN_MODEL_NAME": "Random",
    "PRETRAIN_NUM_ROUNDS": 10,
    "PRETRAIN_NUM_GENERATORS": 10,
    "AGGREGATE": False,
    "DEBUG": False,
    "EARLY_STOP": False,

    "MULTI_TRAFFIC": False,
    "MULTI_RANDOM": False,
}

dic_traffic_env_conf = {
    "ACTION_PATTERN": "set",
    "NUM_INTERSECTIONS": 1,
    "MIN_ACTION_TIME": 10,
    "YELLOW_TIME": 5,
    "ALL_RED_TIME": 0,
    "NUM_PHASES": 2,
    "NUM_LANES": 1,
    "ACTION_DIM": 2,
    "MEASURE_TIME": 10,
    "IF_GUI": True,
    "DEBUG": False,

    "INTERVAL": 1,
    "THREADNUM": 8,
    "SAVEREPLAY": True,
    "RLTRAFFICLIGHT": True,

    "DIC_FEATURE_DIM": dict(
        D_LANE_QUEUE_LENGTH=(4,),
        D_LANE_NUM_VEHICLE=(4,),

        D_COMING_VEHICLE = (4,),
        D_LEAVING_VEHICLE = (4,),

        D_LANE_NUM_VEHICLE_BEEN_STOPPED_THRES1=(4,),
        D_CUR_PHASE=(1,),
        D_NEXT_PHASE=(1,),
        D_TIME_THIS_PHASE=(1,),
        D_TERMINAL=(1,),
        D_LANE_SUM_WAITING_TIME=(4,),
        D_VEHICLE_POSITION_IMG=(4, 60,),
        D_VEHICLE_SPEED_IMG=(4, 60,),
        D_VEHICLE_WAITING_TIME_IMG=(4, 60,),

        D_PRESSURE=(1,),

        D_ADJACENCY_MATRIX=(2,)
    ),

    "LIST_STATE_FEATURE": [
        "cur_phase",
        "time_this_phase",
        "vehicle_position_img",
        "vehicle_speed_img",
        "vehicle_acceleration_img",
        "vehicle_waiting_time_img",
        "lane_num_vehicle",
        "lane_num_vehicle_been_stopped_thres01",
        "lane_num_vehicle_been_stopped_thres1",
        "lane_queue_length",
        "lane_num_vehicle_left",
        "lane_sum_duration_vehicle_left",
        "lane_sum_waiting_time",
        "terminal",

        "coming_vehicle",
        "leaving_vehicle",
        "pressure",

        "adjacency_matrix"

    ],

    "DIC_REWARD_INFO": {
        "flickering": 0,
        "sum_lane_queue_length": 0,
        "sum_lane_wait_time": 0,
        "sum_lane_num_vehicle_left": 0,
        "sum_duration_vehicle_left": 0,
        "sum_num_vehicle_been_stopped_thres01": 0,
        "sum_num_vehicle_been_stopped_thres1": -0.25,
        "pressure": 0,
    },

    "LANE_NUM": {
        "LEFT": 1,
        "RIGHT": 1,
        "STRAIGHT": 1
    },

    "PHASE": [
        'WSES',
        'NSSS',
        'WLEL',
        'NLSL',
        # 'WSWL',
        # 'ESEL',
        # 'NSNL',
        # 'SSSL',
    ],

}

_LS = {"LEFT": 1,
       "RIGHT": 0,
       "STRAIGHT": 1
       }
_S = {
    "LEFT": 0,
    "RIGHT": 0,
    "STRAIGHT": 1
}
_LSR = {
    "LEFT": 1,
    "RIGHT": 1,
    "STRAIGHT": 1
}

DIC_SIMPLEDQN_AGENT_CONF = {
    "LEARNING_RATE": 0.001,
    "SAMPLE_SIZE": 1000,
    "BATCH_SIZE": 20,
    "EPOCHS": 100,
    "UPDATE_Q_BAR_FREQ": 5,
    "UPDATE_Q_BAR_EVERY_C_ROUND": False,
    "GAMMA": 0.8,
    "MAX_MEMORY_LEN": 10000,
    "PATIENCE": 10,
    "D_DENSE": 20,
    "N_LAYER": 2,
    "EPSILON": 0.8,
    "EPSILON_DECAY": 0.95,
    "MIN_EPSILON": 0.2,
    "LOSS_FUNCTION": "mean_squared_error",
    "SEPARATE_MEMORY": False,
    "NORMAL_FACTOR": 20,
    "TRAFFIC_FILE": "cross.2phases_rou01_equal_450.xml",
}

DIC_PATH = {
    "PATH_TO_MODEL": "model/default",
    "PATH_TO_WORK_DIRECTORY": "records/default",
    "PATH_TO_DATA": "data/template",
    "PATH_TO_PRETRAIN_MODEL": "model/default",
    "PATH_TO_PRETRAIN_WORK_DIRECTORY": "records/default",
    "PATH_TO_PRETRAIN_DATA": "data/template",
    ""
    "": "records/initial",
    "PATH_TO_ERROR": "errors/default"
}

DIC_AGENTS = {
    "SimpleDQN": SimpleDQNAgent
}

DIC_ENVS = {
    "anon": AnonEnv
}


import math
import sys

sys.setrecursionlimit(10 ** 5)

t = int(input())

def find(num, i, n, k, tight, ones, zeroes, res, cache):
    if i >= n:
        return zeroes - ones == k
    key = (i, tight, ones)
    if key in cache:
        return cache[key]
    mind = 0
    if tight:
        mind = int(num[i])
    for d in range(mind, 2):
        res[i] = str(d)
        if find(num, i + 1, n, k, tight and d == mind, ones + int(d == 1), zeroes + int(d == 0), res, cache):
            cache[key] = True
            return True
        res[i] = ""
    cache[key] = False
    return False

for _ in range(t):
    n, k = map(int, input().split())
    arr = input()
    res = [""] * n
    found = find(arr, 0, n, k, True, 0, 0, res, {})
    if not found:
        x = k + 2 * math.ceil(max(n - k, 0) / 2)
        if x <= n:
            x += 2
        res = ["1"] + ["0"] * (x - 1)
        for i in range((x - k) // 2 - 1):
            res[-(i + 1)] = "1"
    print("".join(res))


__author__ = 'Administrator'
#coding=utf-8
import urllib2
import os
import urllib
import time
#下载读取网页
def downloadHtml(url):
    return urllib2.urlopen(url).read() #读取全部网页

#下载图片 href
def downloadImg(href,url):
    #获取图片中间路径
    dirname=url[0:url.rfind('/', 1) + 1].replace(href,'')
    #图片存放地址
    img_dir='D:\python\www\pachong'+dirname
    #创建目录
    if not os.path.exists(img_dir):
        #os.makedirs()可以建立递归建立深级目录
        os.makedirs(img_dir)
    #获取图片后缀
    name=os.path.splitext(url)[0].split('/')[-1:]
    exif=os.path.splitext(url)[1]
    filename= '{}{}{}{}'.format(img_dir,os.sep,name[0],exif) #拼接图片地址  os.sep让路径在：linux系统 /  windows系统 \
    #下载图片，并保存到文件夹中
    if not os.path.exists(filename):
        #爬取页面过快造成暂时被网站ban掉的情况，设置time间隔请求
        time.sleep(1)
        urllib.urlretrieve(url,filename)
        print('下载完成')
    else:
        print('下载过了')


from rest_framework import routers
from django.contrib import admin
from django.urls import path
from .views import *

urlpatterns = [
    path('get-token/', CustomObtainAuthToken.as_view(), name = 'get-token'),
    path('balance/', BalanceView.as_view(), name = 'balance')
]

router = routers.SimpleRouter()
router.register('users', UserViewSet)
router.register('ordersequences', OrderSequenceViewSet)
router.register('orders', OrderViewSet)
router.register('ordersequenceresults', OrderSequenceResultViewSet)

urlpatterns += router.urls


class Quiz:
    def __init__(self):
        self.questions = []

    def add_question(self, question, options, correct_option):
        self.questions.append({
            "question": question,
            "options": options,
            "correct_option": correct_option
        })

    def run_quiz(self):
        score = 0
        for i, question_data in enumerate(self.questions, start=1):
            print(f"Question {i}: {question_data['question']}")
            for j, option in enumerate(question_data['options'], start=1):
                print(f"{j}. {option}")
            user_answer = int(input("Your answer: "))
            if user_answer == question_data['correct_option']:
                print("Correct!")
                score += 1
            else:
                print("Incorrect!")
            print()

        print(f"Quiz completed. Your score: {score}/{len(self.questions)}")

def main():
    quiz = Quiz()

    # Add questions
    quiz.add_question("What is the capital of France?", ["London", "Paris", "Berlin"], 2)
    quiz.add_question("Which planet is known as the Red Planet?", ["Earth", "Mars", "Venus"], 2)
    quiz.add_question("Who wrote 'Romeo and Juliet'?", ["Charles Dickens", "William Shakespeare", "Jane Austen"], 2)

    print("Welcome to the Quiz!")
    user_choice = input("Enter 'S' to start the quiz: ").upper()

    if user_choice == 'S':
        quiz.run_quiz()
    else:
        print("Invalid choice. Exiting the quiz.")

if __name__ == "__main__":
    main()


import logging

logging.basicConfig(level="INFO")
logger = logging.getLogger(__name__)

from utils.shadowgen import generator
HETEROGENEITY = [1.0]  # Homogeneous
NUM_MACHINES = 400
SPEC_RANGE = [(50,100)]
MAGNITUDE = 'giga'

SYSTEM_OUTPUT_PATH = 'recipes/routput/basic_spec-{0}.json'.format(
    NUM_MACHINES
)
system_config_path = generator.generate_system_machines(
    SYSTEM_OUTPUT_PATH, NUM_MACHINES, MAGNITUDE, HETEROGENEITY, SPEC_RANGE
)
logger.info(system_config_path)


import torch
import torch.nn as nn

# PyTorch implementation by vinesmsuic
# The paper claimed to use BatchNorm and Leaky ReLu.
# But here we use InstanceNorm instead of BatchNorm.
# We also use reflect padding instead of constant padding here (to reduce artifacts?)

class Discriminator(nn.Module):
    def __init__(self, in_channels=3, out_channels=1, features=[32, 64, 128, 256]):
        super().__init__()
        self.model = nn.Sequential(
            #k3n32s1
            nn.Conv2d(in_channels,features[0],kernel_size=3,stride=1,padding=1,padding_mode="reflect"),
            nn.LeakyReLU(negative_slope=0.2, inplace=True),

            #k3n64s2
            nn.Conv2d(features[0],features[1],kernel_size=3,stride=2,padding=1,padding_mode="reflect"),
            nn.LeakyReLU(negative_slope=0.2, inplace=True),

            #k3n128s1
            nn.Conv2d(features[1],features[2],kernel_size=3,stride=1,padding=1,padding_mode="reflect"),
            nn.InstanceNorm2d(features[2]),
            nn.LeakyReLU(negative_slope=0.2, inplace=True),

            #k3n128s2
            nn.Conv2d(features[2],features[2],kernel_size=3,stride=2,padding=1,padding_mode="reflect"),
            nn.LeakyReLU(negative_slope=0.2, inplace=True),

            #k3n256s1
            nn.Conv2d(features[2],features[3],kernel_size=3,stride=1,padding=1,padding_mode="reflect"),
            nn.InstanceNorm2d(features[3]),
            nn.LeakyReLU(negative_slope=0.2, inplace=True),

            #k3n256s1
            nn.Conv2d(features[3],features[3],kernel_size=3,stride=1,padding=1,padding_mode="reflect"),
            nn.InstanceNorm2d(features[3]),
            nn.LeakyReLU(negative_slope=0.2, inplace=True),

            #k3n1s1
            nn.Conv2d(features[3],out_channels,kernel_size=3,stride=1,padding=1,padding_mode="reflect"),
        )

    def forward(self, x):
        x = self.model(x)
        return x
        #No sigmoid for LSGAN adv loss
        #return torch.sigmoid(x)

def test():
    x = torch.randn((5, 3, 256 ,256))
    model = Discriminator(in_channels=3)
    preds = model(x)
    print(preds.shape)

if __name__ == "__main__":
    test()