import json
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
import dash
from dash.dependencies import Input, Output, State
from jupyter_dash import JupyterDash
from plotly import graph_objects as go
import pickle
from dash.exceptions import PreventUpdate
import numpy as np
from threading import Thread
from statistics import Statistics
from single import Single
import plotly.express as px
import copy

Population, Running, Configs, Stats = None, None, None, None

def create_app(configs, stats):
    global Configs, Stats
    Configs, Stats = configs, stats

    app = JupyterDash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
    server = app.server
    app.layout = html.Div([dcc.Markdown('''##### Run GA configuration'''),
                           dbc.Row([
                           dbc.Col(children=(dcc.Markdown('''###### Selection, recombination, mutation, replacement'''))),
                           dbc.Col(children=(dcc.Markdown('''###### Population parameters'''))),
                           ]),
        dbc.Row([
                           dbc.Col(children=(dcc.Dropdown(id='sel_type',
                                        options=[{'label': opt, 'value': opt}
                                                 for opt in Configs.params['prob_type'].get_functions()],
                                        placeholder='Selection'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='sel_type_error'),
                           dcc.Dropdown(id='rec_type',
                                        options=[{'label': opt, 'value': opt}
                                                 for opt in Configs.params['enc_type'].Cross(Configs.params).get_functions()],
                                        placeholder='Recombination'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='rec_type_error'),
                           dbc.Collapse(dbc.Input(id='n_crossover_value',
                                                  type = 'number',
                                                  placeholder='Number of Crossover Points',
                                                  min=0,
                                                  max=Configs.params['gene_size']),
                                        id='n_crossover_value_collapse'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='n_crossover_value_error'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('n must be in the range from 0 to gene size')),
                                        id='n_crossover_value_wrong'),
                           dbc.Collapse(dbc.Input(id='alpha',
                                                  type = 'number',
                                                  placeholder='Blending Ratio',
                                                  min=0,
                                                  max=1),
                                        id='alpha_collapse'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='alpha_error'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('alpha must be be in the range from 0 to 1')),
                                        id='alpha_wrong'),
                           dcc.Dropdown(id='mut_type',
                                        options=[{'label': opt, 'value': opt}
                                                 for opt in Configs.params['enc_type'].Mutation(Configs.params).get_functions()],
                                        placeholder='Mutation'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='mut_type_error'),
                           dbc.Collapse(dbc.Input(id='theta',
                                                  type = 'number',
                                                  placeholder='Standard Deviation',
                                                  min=0),
                                        id='theta_collapse'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='theta_error'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('Theta must be non-negative')),
                                        id='theta_wrong'),
                           dcc.Dropdown(id='rep_type',
                                        options=[{'label': opt, 'value': opt}
                                                 for opt in Configs.params['prob_type'].get_functions()],
                                        placeholder='Replacement'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='rep_type_error'))),

                           dbc.Col(children=(dbc.Input(id='pop_size',
                                     placeholder='Population Size',
                                     type='number',
                                     min=4, max=128,
                                     step=2),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='pop_size_error'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('Population size must be in the range from 1 to 128')),
                                        id='pop_size_wrong'),
                           dbc.Input(id='par_size',
                                     placeholder='Num. Parents',
                                     type='number',
                                     min=2, max=64,
                                     step=2),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='par_size_error'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('Parent size must be non-negative')),
                                                id='wrong_par_size'),
                           dbc.Input(id='off_size',
                                     placeholder='Num. Offspring',
                                     type='number',
                                     min=2, max=64,
                                     step=2),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='off_size_error'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('Children size must be non-negative')),
                                                id='wrong_off_size'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('Parent and children size must be greater than or equal to population size')),
                                        id='par_chi_error'),
                           dbc.Collapse(dcc.Dropdown(id='tourn_size',
                                        options=[{'label': '2',
                                                  'value': 2},
                                                {'label': '4',
                                                  'value': 4},
                                                {'label': '8',
                                                  'value': 8},
                                                {'label': '16',
                                                  'value': 16},
                                                {'label': '32',
                                                  'value': 32},
                                                {'label': '64',
                                                  'value': 64}],
                                        placeholder='Tournament Size'),
                                        id='tourn_size_collapse'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='tourn_size_error'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('Tournament size must be in the range from 0 to the minimum of parent size and population size')),
                                        id='tourn_parent_error'),
                           dbc.Input(id='mut_rate',
                                     placeholder='Mutation Rate',
                                     type='number',
                                     min=0, max=1,
                                     step=0.01),
                           dbc.Collapse(dbc.Card(dbc.CardBody('This is a required field')),
                                        id='mut_rate_error'),
                           dbc.Collapse(dbc.Card(dbc.CardBody('Mutation rate must be in the range from 0 to 1')),
                                        id='mut_rate_wrong'))),
                            ]),
                           dbc.Button(id='save',
                                      children='Save'),

                           dbc.Button(id='start',
                                      children='Start',
                                      disabled=True),
                           dbc.Button(id='stop',
                                      children='Stop',
                                      disabled=True),
                           dbc.Button(id='restart',
                                      children='Restart',
                                      disabled=True),
                           dbc.Button(id='pause',
                                      children='Pause',
                                      disabled=True),
                           dbc.Button(id='resume',
                                      children='Resume',
                                      disabled=True),
        dbc.Row([
                           dbc.Col(children=(html.Div(id='custom',
                                    children=[dcc.Graph(figure=go.Figure())]))),
                          dbc.Col(children=( dcc.Graph(id='curr_pop',
                                     figure=go.Figure()),
                           dcc.Interval(id='interval',
                                        disabled=True,
                                        interval=1500)))
        ]),
                           dcc.Graph(id='fitness',
                                     figure=go.Figure())])

    @app.callback(
        Output('fitness', 'figure'),
        Input('interval', 'n_intervals')
    )
    def update_fitness(n):
        fig = go.Figure()

        line_colors = px.colors.qualitative.Plotly
        colors = ['rgba(99,110,250,0.5)', 'rgba(239,85,59,0.5)', 'rgba(0,204,150,0.5)']
        for i in range(configs.params['num_objs']):
            fig.add_trace(go.Scatter(y=Stats.adhoc['fitness']['maxs'][i],
                                     mode=None,
                                     fill=None,
                                     opacity=0,
                                     showlegend=False))
            fig.add_trace(go.Scatter(y=Stats.adhoc['fitness']['maxs'][i],
                                     mode='lines',
                                     fill='tonexty',
                                     line_color=line_colors[i],
                                     legendgroup=str(i),
                                     name='Max. ' + Configs.params['obj_names'][i]))
            fig.add_trace(go.Scatter(y=Stats.adhoc['fitness']['avgs'][i],
                                     name='Avg. ' + Configs.params['obj_names'][i],
                                     fill='tonexty',
                                     line_color=line_colors[i],
                                     legendgroup=str(i),
                                     mode='lines'))
            fig.add_trace(go.Scatter(y=Stats.adhoc['fitness']['mins'][i],
                                     mode=None,
                                     name='Min. ' + Configs.params['obj_names'][i],
                                     line_color=line_colors[i],
                                     legendgroup=str(i),
                                     fill='tonexty'))

        fig.update_layout(title='Fitness Convergence',
                              xaxis_title='Generations',
                              yaxis_title='Fitness Value')

        return fig

    @app.callback(
        Output('custom', 'children'),
        Input('interval', 'n_intervals'), prevent_initial_call = True
    )
    def update_custom(n):
        if Configs.params['cust_vis'] == None:
            return dcc.Graph(figure=go.Figure())
        else:
            if Configs.params['num_objs'] == 1:
                best = Configs.params['prob_type'].rank_based(Population,
                                                                 Configs.params['pop_size'],
                                                                 1)[0]
            else:
                best = Configs.params['prob_type'].NSGA_II(copy.deepcopy(Population),
                                                              Configs.params['pop_size'],
                                                              1)[0]
            return Configs.params['cust_vis'](Configs, best)

    @app.callback(
        Output('curr_pop', 'figure'),
        Input('interval', 'n_intervals'), prevent_initial_call = True
    )
    def update_curr_pop(n):
        fig = go.Figure(data=[go.Heatmap(z=[ind['gene'] for ind in Population])])
        fig.update_layout(title='Population ' + Configs.params['enc_name'] + ' Distribution',
                          xaxis_title=Configs.params['enc_name'], yaxis_title='Candidate Solution')
        return fig

    @app.callback(
        Output('save', 'disabled'),
        Input('start', 'n_clicks'),
        Input('resume', 'n_clicks'),
        Input('pause', 'n_clicks'),
        Input('stop', 'n_clicks'), prevent_initial_call=True
    )
    def enable_save(startclicks, resumeclicks, pauseclicks, stopclicks):
        ctx = dash.callback_context
        if ctx.triggered[0]['prop_id'] == 'start.n_clicks':
            return True
        elif ctx.triggered[0]['prop_id'] == 'pause.n_clicks':
            return False
        elif ctx.triggered[0]['prop_id'] == 'resume.n_clicks':
            return True
        elif ctx.triggered[0]['prop_id'] == 'stop.n_clicks':
            return False

    @app.callback(
        Output('start', 'disabled'),
        Input('start', 'n_clicks'),
        Input('save', 'n_clicks'),
        State('resume', 'disabled'),
        State('sel_type', 'value'),
        State('rec_type', 'value'),
        State('mut_type', 'value'),
        State('rep_type', 'value'),
        State('pop_size', 'value'),
        State('par_size', 'value'),
        State('off_size', 'value'),
        State('mut_rate', 'value'),
        State('n_crossover_value', 'value'),
        State('tourn_size', 'value'),
        State('alpha', 'value'),
        State('theta', 'value'),
        State('n_crossover_value_collapse', 'is_open'),
        State('tourn_size_collapse', 'is_open'),
        State('alpha_collapse', 'is_open'),
        State('theta_collapse', 'is_open'), prevent_initial_call=True
    )
    def enable_start(start_clicks, save_clicks, resume_dis, sel_type, rec_type, mut_type, rep_type, pop_size, par_size, off_size, mut_rate, n_crossover, tourn_size, alpha, theta, n_open, tourn_open, alpha_open, theta_open):

        ctx = dash.callback_context
        if ctx.triggered[0]['prop_id'] == 'start.n_clicks':
            return True
        elif ctx.triggered[0]['prop_id'] == 'save.n_clicks':
            if None in (sel_type, rec_type, mut_type, rep_type, pop_size, par_size, off_size, mut_rate):
                raise PreventUpdate
            elif alpha is None and alpha_open == True:
                raise PreventUpdate
            elif theta is None and theta_open == True:
                raise PreventUpdate
            elif tourn_size is None and tourn_open == True:
                raise PreventUpdate
            elif n_crossover is None and n_open == True:
                raise PreventUpdate
            elif mut_rate < 0 or mut_rate > 1:
                raise PreventUpdate
            elif pop_size < 1 or pop_size > 128:
                raise PreventUpdate
            elif tourn_open == True and (tourn_size < 0 or (tourn_size > par_size) or (tourn_size > pop_size)):
                raise PreventUpdate
            elif (par_size + off_size) < pop_size:
                raise PreventUpdate
            elif par_size < 0:
                raise PreventUpdate
            elif off_size < 0:
                raise PreventUpdate
            elif n_crossover is not None and n_crossover < 0:
                raise PreventUpdate
            elif alpha is not None and (alpha < 0 or alpha > 1):
                raise PreventUpdate
            elif theta is not None and (theta < 0 or theta > (Configs.params['max_value'] - Configs.params['min_value']) / 10):
                raise PreventUpdate

            if sel_type == 'rank-based':
                Configs.params['sel_type'] = Configs.params['prob_type'].rank_based
            elif sel_type == 'tournament':
                Configs.params['sel_type'] = Configs.params['prob_type'].tournament
            elif sel_type == 'NSGA-II':
                Configs.params['sel_type'] = Configs.params['prob_type'].NSGA_II

            # add other parent selection options here

            if rec_type == 'order':
                Configs.params['enc_type'].params['rec_type'] = Configs.params['enc_type'].Cross(Configs.params).order
            elif rec_type == 'partially-mapped':
                Configs.params['enc_type'].params['rec_type'] = Configs.params['enc_type'].Cross(Configs.params).PMX
            elif rec_type == 'whole-arithmetic':
                Configs.params['enc_type'].params['rec_type'] = Configs.params['enc_type'].Cross(Configs.params).whole_arithmetic
            elif rec_type == 'simple-arithmetic':
                Configs.params['enc_type'].params['rec_type'] = Configs.params['enc_type'].Cross(Configs.params).simple_arithmetic
            elif rec_type == 'n-point':
                Configs.params['enc_type'].params['rec_type'] = Configs.params['enc_type'].Cross(Configs.params).n_point
            elif rec_type == 'uniform':
                Configs.params['enc_type'].params['rec_type'] = Configs.params['enc_type'].Cross(Configs.params).uniform

            # add other crossover options here

            if mut_type == 'swap':
                Configs.params['enc_type'].params['mut_type'] = Configs.params['enc_type'].Mutation(Configs.params).swap
            elif mut_type == 'scramble':
                Configs.params['enc_type'].params['mut_type'] = Configs.params['enc_type'].Mutation(Configs.params).scramble
            elif mut_type == 'uniform':
                Configs.params['enc_type'].params['mut_type'] = Configs.params['enc_type'].Mutation(Configs.params).uniform
            elif mut_type == 'non-uniform':
                Configs.params['enc_type'].params['mut_type'] = Configs.params['enc_type'].Mutation(Configs.params).non_uniform
            elif mut_type == 'random-resetting':
                Configs.params['enc_type'].params['mut_type'] = Configs.params['enc_type'].Mutation(Configs.params).random_resetting
            elif mut_type == 'creep':
                Configs.params['enc_type'].params['mut_type'] = Configs.params['enc_type'].Mutation(Configs.params).creep
            elif mut_type == 'bit-flip':
                Configs.params['enc_type'].params['mut_type'] = Configs.params['enc_type'].Mutation(Configs.params).bit_flip

            # add other mutation options here

            if rep_type == 'rank-based':
                Configs.params['rep_type'] = Configs.params['prob_type'].rank_based
            elif rep_type == 'tournament':
                Configs.params['rep_type'] = Configs.params['prob_type'].tournament
            elif rep_type == 'NSGA-II':
                Configs.params['rep_type'] = Configs.params['prob_type'].NSGA_II

            # add other survivor selection options here

            Configs.params['pop_size'] = pop_size
            Configs.params['par_size'] = par_size
            Configs.params['off_size'] = off_size
            Configs.params['mut_rate'] = mut_rate
            Configs.params['tourn_size'] = tourn_size
            Configs.params['alpha'] = alpha
            Configs.params['theta'] = theta
            Configs.params['n'] = n_crossover

            if resume_dis == True:
                return False
            else:
                return True

    @app.callback(
        Output('pause', 'disabled'),
        Input('start', 'n_clicks'),
        Input('resume', 'n_clicks'),
        Input('pause', 'n_clicks'), prevent_initial_call=True
    )
    def enable_pause(startclicks, resumeclicks, stopclicks):
        ctx = dash.callback_context
        if ctx.triggered[0]['prop_id'] == 'start.n_clicks':
            return False
        elif ctx.triggered[0]['prop_id'] == 'pause.n_clicks':
            return True
        elif ctx.triggered[0]['prop_id'] == 'resume.n_clicks':
            return False

    @app.callback(
        Output('resume', 'disabled'),
        Input('stop', 'n_clicks'),
        Input('resume', 'n_clicks'),
        Input('pause', 'n_clicks'), prevent_initial_call=True
    )
    def enable_resume(stopclicks, resumeclicks, pauseclicks):
        ctx = dash.callback_context
        if ctx.triggered[0]['prop_id'] == 'stop.n_clicks':
            return True
        elif ctx.triggered[0]['prop_id'] == 'resume.n_clicks':
            return True
        elif ctx.triggered[0]['prop_id'] == 'pause.n_clicks':
            return False

    @app.callback(
        Output('stop', 'disabled'),
        Input('stop', 'n_clicks'),
        Input('resume', 'n_clicks'),
        Input('pause', 'n_clicks'), prevent_initial_call=True
    )
    def enable_stop(stopclicks, resumeclicks, pauseclicks):
        ctx = dash.callback_context
        if ctx.triggered[0]['prop_id'] == 'stop.n_clicks':
            return True
        elif ctx.triggered[0]['prop_id'] == 'resume.n_clicks':
            return True
        elif ctx.triggered[0]['prop_id'] == 'pause.n_clicks':
            return False

    @app.callback(
        Output('interval', 'disabled'),
        Input('pause', 'n_clicks'),
        Input('start', 'n_clicks'),
        Input('resume', 'n_clicks'), prevent_initial_call=True
    )
    def enable_interval(pauseclicks, startclicks, resumeclicks):
        global Running

        ctx = dash.callback_context
        if ctx.triggered[0]['prop_id'] == 'pause.n_clicks':
            Running = False
            return True
        elif ctx.triggered[0]['prop_id'] == 'start.n_clicks':
            Thread(target=start_GA, args=()).start()
            return False
        elif ctx.triggered[0]['prop_id'] == 'resume.n_clicks':
            Thread(target=resume_GA, args=()).start()
            return False

    @app.callback(
        Output('n_crossover_value_collapse', 'is_open'),
        Input('rec_type', 'value')
    )
    def enable_n_point(value):
        if value == 'n-point':
            return True
        else:
            return False

    @app.callback(
        Output('tourn_size_collapse', 'is_open'),
        Input('sel_type', 'value'),
        Input('rep_type', 'value')
    )
    def enable_tourn_size(sel_type, rep_type):
        if sel_type == 'tournament' or rep_type == 'tournament':
            return True
        else:
            return False

    @app.callback(
        Output('alpha_collapse', 'is_open'),
        Input('rec_type', 'value')
    )
    def enable_alpha(value):
        if value == 'whole-arithmetic' or value == 'simple-arithmetic':
            return True
        else:
            return False

    @app.callback(
        Output('theta_collapse', 'is_open'),
        Input('mut_type', 'value')
    )
    def enable_theta(value):
        if value == 'non-uniform' or value == 'creep':
            return True
        else:
            return False

    @app.callback(
        Output('sel_type_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('sel_type', 'value'), prevent_initial_call=True
    )
    def no_sel_type(n, value):
        if n:
            if value is None:
                return True
        return False

    @app.callback(
        Output('rec_type_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('rec_type', 'value'), prevent_initial_call=True
    )
    def no_rec_type(n, value):
        if n:
            if value is None:
                return True
        return False

    @app.callback(
        Output('n_crossover_value_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('n_crossover_value', 'value'),
        State('n_crossover_value_collapse', 'is_open'), prevent_initial_call=True
    )
    def no_n(n, value, is_open):
        if n is not None and is_open == True:
            if value is None:
                return True
        return False

    @app.callback(
        Output('n_crossover_value_wrong', 'is_open'),
        Input('save', 'n_clicks'),
        State('n_crossover_value', 'value'),
        State('n_crossover_value_collapse', 'is_open'), prevent_initial_call=True
    )
    def wrong_n(n, value, is_open):
        if n is not None and is_open == True:
            if value < 0 or value >= Configs.params['gene_size']:
                return True
        return False

    @app.callback(
        Output('mut_type_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('mut_type', 'value'), prevent_initial_call=True
    )
    def no_mut_type(n, value):
        if n:
            if value is None:
                return True
        return False

    @app.callback(
        Output('rep_type_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('rep_type', 'value'), prevent_initial_call=True
    )
    def no_rep_type(n, value):
        if n:
            if value is None:
                return True
        return False

    @app.callback(
        Output('pop_size_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('pop_size', 'value'), prevent_initial_call=True
    )
    def no_pop_size(n, value):
        if n:
            if value is None:
                return True
        return False

    @app.callback(
        Output('par_size_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('par_size', 'value'), prevent_initial_call=True
    )
    def no_par_size(n, value):
        if n:
            if value is None:
                return True
        return False

    @app.callback(
        Output('off_size_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('off_size', 'value'), prevent_initial_call=True
    )
    def no_off_size(n, value):
        if n:
            if value is None:
                return True
        return False

    @app.callback(
        Output('mut_rate_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('mut_rate', 'value'), prevent_initial_call=True
    )
    def no_mut_rate(n, value):
        if n:
            if value is None:
                return True
        return False

    @app.callback(
        Output('mut_rate_wrong', 'is_open'),
        Input('save', 'n_clicks'),
        State('mut_rate', 'value'), prevent_initial_call=True
    )
    def wrong_mut_rate(n, value):
        if None not in (n, value):
            if value < 0 or value > 1:
                return True
        return False

    @app.callback(
        Output('pop_size_wrong', 'is_open'),
        Input('save', 'n_clicks'),
        State('pop_size', 'value'), prevent_initial_call=True
    )
    def wrong_pop_size(n, value):
        if None not in (n, value):
            if value < 1 or value > 128:
                return True
        return False

    @app.callback(
        Output('wrong_off_size', 'is_open'),
        Input('save', 'n_clicks'),
        State('off_size', 'value'), prevent_initial_call=True
    )
    def wrong_off_size(n, value):
        if None not in (n, value):
            if value < 0:
                return True
        return False

    @app.callback(
        Output('wrong_par_size', 'is_open'),
        Input('save', 'n_clicks'),
        State('par_size', 'value'), prevent_initial_call=True
    )
    def wrong_par_size(n, value):
        if None not in (n, value):
            if value < 0:
                return True
        return False

    @app.callback(
        Output('tourn_size_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('tourn_size', 'value'),
        State('tourn_size_collapse', 'is_open'), prevent_initial_call=True
    )
    def no_tourn_size(n, value, is_open):
        if n is not None and is_open == True:
            if value is None:
                return True
        return False

    @app.callback(
        Output('alpha_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('alpha', 'value'),
        State('alpha_collapse', 'is_open'), prevent_initial_call=True
    )
    def no_alpha(n, value, is_open):
        if n is not None and is_open == True:
            if value is None:
                return True
        return False

    @app.callback(
        Output('alpha_wrong', 'is_open'),
        Input('save', 'n_clicks'),
        State('alpha', 'value'),
        State('alpha_collapse', 'is_open'), prevent_initial_call=True
    )
    def wrong_alpha(n, value, is_open):
        if n is not None and is_open == True:
            if value < 0 or value > 1:
                return True
        return False

    @app.callback(
        Output('theta_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('theta', 'value'),
        State('theta_collapse', 'is_open'), prevent_initial_call=True
    )
    def no_theta(n, value, is_open):
        if n is not None and is_open == True:
            if value is None:
                return True
        return False

    @app.callback(
        Output('theta_wrong', 'is_open'),
        Input('save', 'n_clicks'),
        State('theta', 'value'),
        State('theta_collapse', 'is_open'), prevent_initial_call=True
    )
    def wrong_theta(n, value, is_open):
        if n is not None and is_open == True:
            if value < 0 or value > (Configs.params['max_value'] - Configs.params['min_value']) / 10:
                return True
        return False

    @app.callback(
        Output('tourn_parent_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('tourn_size', 'value'),
        State('par_size', 'value'),
        State('pop_size', 'value'), prevent_initial_call=True
    )
    def tourn_par_error(n, tourn_size, par_size, pop_size):
        if None not in (n, tourn_size, par_size, pop_size):
            if tourn_size < 0 or (tourn_size > par_size) or (tourn_size > pop_size):
                return True
        return False

    @app.callback(
        Output('par_chi_error', 'is_open'),
        Input('save', 'n_clicks'),
        State('par_size', 'value'),
        State('off_size', 'value'),
        State('pop_size', 'value'), prevent_initial_call=True
    )
    def par_chi_error(n, par_size, off_size, pop_size):
        if None not in (n, par_size, off_size, pop_size):
            if (par_size + off_size) < pop_size:
                return True
        return False

    return app

def start_GA():
    global Population, Running

    Stats.setup()
    Population = Configs.params['enc_type'].initialize()
    Population = Configs.params['eval_type'](Configs, Population)

    Running = True
    while Running:
        parents = Configs.params['sel_type'](Population,
                                             Configs.params['pop_size'],
                                             Configs.params['par_size'])
        offspring = Configs.params['enc_type'].mate(parents)
        offspring = Configs.params['enc_type'].params['mut_type'](offspring)
        offspring = Configs.params['eval_type'](Configs, offspring)
        Population = Configs.params['rep_type'](np.concatenate((Population, offspring), axis=0),
                                                Configs.params['pop_size'] + Configs.params['off_size'],
                                                Configs.params['pop_size'])
        Stats.update_dynamic(Population)

    Stats.update_static(Population)

def resume_GA():
    global Population, Running

    Running = True
    while Running:
        parents = Configs.params['sel_type'](Population,
                                             Configs.params['pop_size'],
                                             Configs.params['par_size'])
        offspring = Configs.params['enc_type'].mate(parents)
        offspring = Configs.params['enc_type'].params['mut_type'](offspring)
        offspring = Configs.params['eval_type'](Configs, offspring)
        Population = Configs.params['rep_type'](np.concatenate((Population, offspring)),
                                                Configs.params['pop_size'] + Configs.params['off_size'],
                                                Configs.params['pop_size'])
        Stats.update_dynamic(Population)

    Stats.update_static(Population)


import sys
import os
import argparse
import subprocess
import threading

from multiprocessing import Pool

__project__ = 'gradcrawler'
__version__ = '0.3.10'
__repo__ = 'https://github.com/cullengao/gradcrawler'

def _print_version():
    sv = sys.version_info
    py_version = '{}.{}.{}'.format(sv.major, sv.minor, sv.micro)
    version_parts = __version__.split('.')
    s = '{} version: [{}], Python {}'.format(__project__, __version__, py_version)
    s += "\nMajor version: {}  (breaking changes)".format(version_parts[0])
    s += "\nMinor version: {}  (extra feature)".format(version_parts[1])
    s += "\nMicro version: {} (commit count)".format(version_parts[2])
    s += "\nPlease refer to the most recent version at {}".format(__repo__)
    return s

def _get_args_parse():
    desc = 'SJTU Graduate Design Project - GradCrawler, by Hang Gao (@cullengao)' \
        + '\nFeel free to try out commands, if anything is missing it will print help.' \
        + '\n\nYou would like to start with `python gradcrawler.py -h`'
    p = argparse.ArgumentParser(description=desc, formatter_class=argparse.RawTextHelpFormatter)
    p.add_argument('--version', '-v', action='version', version=_print_version())
    p.add_argument('--crawler', '-c', required=True, help='A name-tag for crawler to start.')
    p.add_argument('--threads', '-t', type=int, default=1, help='Number of scraping threads.')
    return p

def _call(command):
    subprocess.call(command)
    return

if __name__ == '__main__':
    parser = _get_args_parse()
    p_dict = vars(parser.parse_args())
    try:
        n_threads, crawler_name = tuple(p_dict.values())
    except Exception:
        raise ValueError('Invalid input, please check for command specification.')
    # Change to the working directory
    os.chdir('../src/')

    # Execute command by subprocess
    main_command = ['scrapy', 'crawl', crawler_name]
    redis_command = ['redis-server', '../db/redis/']
    mongo_command = ['mongod', '-dbpath', '../db/mongod/']

    # Extra 2 threads for mongoDB and redis-server
    threading.Thread(target=_call(redis_command)).start()
    threading.Thread(target=_call(mongo_command)).start()

    pool = Pool(n_threads)
    pool.map_async(_call(main_command), '')

    pool.close()
    pool.join()
    sys.exit(0)


#!/user/bin/env python
#-*-coding:utf-8-*-

'''
Created on 2015年10月15日

@author: zhuxiaobing
'''

import db
import time
import logging

_triggers=frozenset(['pre_insert','pre_update','pre_delete'])

def _gen_sql(table_name,mappings):
    """由类到表，自动生成SQL语句"""
    pk=None
    sql=['**generating SQL for %s:'%table_name,'create table `%s`('%table_name]
    for f in sorted(mappings.values(),lambda x, y :cmp(x._order, y._order)):
        if not hasattr(f, 'ddl'):
            raise StandardError('no ddl in field "%s".'%f)
        ddl = f.ddl
        nullable=f.unllable
        if f.primary_key:
            pk=f.name
        sql.append(' `%s` %s,'%(f.name,ddl) if nullable else ' `%s` %s not null,'%(f.name,ddl))
    sql.append(' primary key (`%s`)'%pk)
    sql.append(');')
    return '\n'.join(sql )

class Field(object):
    """保存数据库中的表的字段属性,表明每个字段是否可以更改，是否可以插入，是否有默认值，是否是主键等"""
    _count=0

    def __init__(self,**kw):
        self.name=kw.get('name',None)
        self._default=kw.get('default',None)
        self.primary_key=kw.get('primary_key',False)
        self.nullable=kw.get('nullable',False)
        self.updatable=kw.get('updatable',True)
        self.insertable=kw.get('insertable',True)
        self.ddl=kw.get('ddl','')
        self._order=Field._count
        Field._count+=1

    @property
    def default(self):
        d =self._default
        return d() if callable( d) else d

    def __str__(self):
        """返回表中每个字段 各个属性 的描述"""
        s=['<%s:%s,%s,default(%s),'%(self.__class__.__name__,self.name,self.ddl,self._default)]
        self.nullable and s.append('N')
        self.updatable and s.append("U")
        self.insertable and s.append("I")
        s.append('>')
        return " ".join(s )

class StringField(Field):
    """定义String类型的Field域"""
    def __init__(self,**kw):
        if 'default' not in kw:
            kw['default'] = ''
        if 'ddl' not in kw:
            kw['ddl'] = 'varchar(255)'
        super(StringField, self).__init__(**kw)

class IntegerField(Field):
    """保存Integer类型字段的属性"""
    def __init__(self, **kw):
        if 'default' not in kw:
            kw['default'] = 0
        if 'ddl' not in kw:
            kw['ddl'] = 'bigint'
        super(IntegerField, self).__init__(**kw)

class FloatField(Field):
    """
    保存Float类型字段的属性
    """
    def __init__(self, **kw):
        if 'default' not in kw:
            kw['default'] = 0.0
        if 'ddl' not in kw:
            kw['ddl'] = 'real'
        super(FloatField, self).__init__(**kw)

class BooleanField(Field):
    """
    保存BooleanField类型字段的属性
    """
    def __init__(self, **kw):
        if not 'default' in kw:
            kw['default'] = False
        if not 'ddl' in kw:
            kw['ddl'] = 'bool'
        super(BooleanField, self).__init__(**kw)

class TextField(Field):
    """
    保存Text类型字段的属性
    """
    def __init__(self, **kw):
        if 'default' not in kw:
            kw['default'] = ''
        if 'ddl' not in kw:
            kw['ddl'] = 'text'
        super(TextField, self).__init__(**kw)

class BlobField(Field):
    """
    保存Blob类型字段的属性
    """
    def __init__(self, **kw):
        if 'default' not in kw:
            kw['default'] = ''
        if 'ddl' not in kw:
            kw['ddl'] = 'blob'
        super(BlobField, self).__init__(**kw)

class VersionField(Field):
    """
    保存Version类型字段的属性
    """
    def __init__(self, name=None):
        super(VersionField, self).__init__(name=name, default=0, ddl='bigint')

class ModelMetaclass(type):
    """
    此类事用来定制类对象的，注意python中的所有东西都是对象，包括类也是。
    这个类主要做一下几件事：
    1，排除对Model类的定制，让Model类保持原样。
    2，属性和字段的Mapping。并将映射的结果保存在mapping变量中。
    3，表名和类的映射，提取类名，并赋值给表名，同时使用__table__属性保存表名。
    """
    def __new__(cls,name,bases,attrs):
        if name=='Model':
            return type.__new__(cls,name,bases,attrs )
        if not hasattr(cls,'subclasses'):
            cls.subclasses={}
        if not name in cls.subclasses:
            cls.subclasses[name ]=name
        else:
            logging.warning("Redefine class :%s"%name )

        logging.info("Scan ORMapping %s..."%name )
        mappings=dict()
        primary_key=None
        for k ,v in attrs.iteritems():
            if isinstance(v, Field ):
                if not v.name:
                    v.name=k
                logging.info('[MAPPING]Found mapping :%s==>%s'%(k,v ))
                if v.primary_key:
                    if primary_key:
                        raise TypeError('Cannot define more thean 1 primary key in class :%s'% name)
                    if v.updatable:
                        logging.warning('NOTE:change primary key to non-updatable')
                        v.updatable=False
                    if v.nullable:
                        logging.warning('NOTE: change primary key to non-nullable.')
                        v.nullable = False
                    primary_key = v
                mappings[ k]=v
        if not primary_key:
            raise TypeError('Primary key not define in class :%s '%name )
        for k in mappings.iterkeys():
            attrs.pop(k )
        if not '__table__' in attrs:
            attrs['__table__']=name.lower()
        attrs['__mappings__']=mappings
        attrs['__primary_key__']=primary_key
        attrs['__sql__']=lambda self:_gen_sql(attrs['__table__'], mappings)
        for trigger in _triggers:
            if not trigger in attrs:
                attrs[trigger ]=None
        return type.__new__(cls,name,bases, attrs)

class Model(dict ):

    """这是该项目本身所有类的基类，"""

    __metaclass__=ModelMetaclass

    def __init__(self,**kw):
        """由于所有的实体类继承自Model,而Model继承自dict,所以，其实所有的实体类都是字典，从而调用dict中的赋值方法来实现对象的初始化。"""
        super(Model,self).__init__(**kw )

    def __getattr__(self,key ):
        try:
            return self[key ]
        except KeyError:
            raise AttributeError(r"'DICT' Object has no attribute '%s'"%key )

    def __setattr__(self,key,value ):
        self[key ]=value

    @classmethod
    def get(cls,pk):
        """类方法：通过主键来取得数据项"""
        d=db.select_one('select * from %s where %s =?'%(cls.__table__,cls.__primary_key__.name),pk)
        return cls(**d ) if d else None

    @classmethod
    def find_first(cls,where,*args ):
        """类方法：通过Where条件查询结果，如果有多个，取第一个，如果没有，None"""
        d = db.select_one('select * from %s %s' % (cls.__table__, where), *args)
        return cls(**d) if d else None

    @classmethod
    def find_all(cls, *args):
        L = db.select('select * from `%s`' % cls.__table__)
        return [cls(**d) for d in L]

    @classmethod
    def find_by(cls, where, *args):
        L = db.select('select * from `%s` %s' % (cls.__table__, where), *args)
        return [cls(**d) for d in L]

    @classmethod
    def count_all(cls):
        return db.select_int('select count(`%s`) from `%s`'%(cls.__primary_key__.name,cls.__table__))

    @classmethod
    def count_by(cls,where,*args ):
        return db.select_int('select count(`%s`) from `%s` %s '%(cls.__primary_key__.name,cls.__table__,where ),*args )

    def update(self):
        self.pre_update and self.pre_update()
        L=[]
        args=[]
        for k,v in self.__mappings__.iteritems():
            if v.updatable:
                if hasattr(self, k ):
                    arg=getattr(self, k )
                else:
                    arg=v.default
                    setattr(self,k,arg )
                L.append('`%s`=?'%k )
                args.append(arg)
        pk=self.__primary_key__.name
        args.append(getattr(self, pk))
        db.update('update `%s` set %s where %s =?'%(self.__table__,','.join(L),pk),*args )
        return self

    def delete(self):
        self.pre_delete and self.pre_delete()
        pk = self.__primary_key__.name
        args = (getattr(self, pk), )
        db.update('delete from `%s` where `%s`=?' % (self.__table__, pk), *args)
        return self

    def insert(self):
        self.pre_insert and self.pre_insert()
        params = {}
        for k, v in self.__mappings__.iteritems():
            if v.insertable:
                if not hasattr(self, k):
                    setattr(self, k, v.default)
                params[v.name] = getattr(self, k)
        db.insert('%s' % self.__table__, **params)
        return self

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    db.create_engine('root', 'ROOT', 'test', '127.0.0.1')
    db.update('drop table if exists user')
    db.update('create table user (id int primary key, name text, email text, passwd text, last_modified real)')
    import doctest
    doctest.testmod()


import pandas as pd
from selection import load_data
from seasonality_detection import ljung_box_test
from dtw_check import dtw_check
from hypothesis_2 import arima_seasonality_added_rolling
from hypothesis_2 import arima_rolling_011
from hypothesis_2 import arima_seasonality_added_rolling_011
from hypothesis_2 import arima_rolling
from selection import individual_series
from stl_decompose import product_seasonal_comp_7_point
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
import matplotlib.pyplot as plt
import time
import os

def moving_average(input_df, order=12):
    input_df_copy = input_df.copy()
    input_df_copy["prediction"] = input_df_copy["quantity"]
    for i in range(16, 0, -1):
        input_df_copy["prediction"].iloc[-i] = input_df_copy.iloc[-i-order:-i]["quantity"].mean()
    return input_df_copy

def moving_average_with_seasonality(input_df, product_seasonal_comp_7_point, order=36):
    input_df_copy = input_df.copy().set_index("dt_week")
    seasonality_component_copy = product_seasonal_comp_7_point.copy()
    seasonality_component_copy.columns = ["seasonal_quantity"]
    input_df_copy = pd.concat([input_df_copy, seasonality_component_copy], axis=1).dropna(subset=["quantity"])
    min_seasonal_value = input_df_copy["seasonal_quantity"].min()
    # print(min_seasonal_value)
    input_df_copy["seasonal_quantity"] = input_df_copy["seasonal_quantity"] + abs(min_seasonal_value*2)
    input_df_copy["prediction"] = input_df_copy["quantity"]
    for i in range(16, 0, -1):
        seasonal_rolling_mean = input_df_copy.iloc[-i-order:-i]["seasonal_quantity"].mean()
        # print(input_df_copy)
        f = (input_df_copy.iloc[-i]["seasonal_quantity"] - seasonal_rolling_mean)/seasonal_rolling_mean
        x = input_df_copy.iloc[-i-order:-i]["quantity"].mean()
        input_df_copy["prediction"].iloc[-i] = x + x*f
    return input_df_copy

def moving_average_available(input_df, product_product_seasonal_comp_7_point, order=52):
    """
    prediction of last 16 points using moving average of order 52 .if datapoints available is less than 52, will consid-
    er only those number of points.Decreasing factor is calculated using same number of points from seasonal component.
    :param input_df: customer-product level data
    :param product_product_seasonal_comp_7_point: product level seasonal smoothened data
    :param order: moving average max order
    :return: input_df with one more column with predictions
    """
    input_df_copy = input_df.copy()
    seasonal_copy = product_seasonal_comp_7_point.copy()
    num_weeks = input_df_copy.shape[0]
    # if num_weeks >= 68:
    #
    # else:
    #     order = num_weeks - 16
    return output_df

project = "/home/aman/PycharmProjects/seasonality_hypothesis/"
folder = "category_10"
file = "report.csv"
folder_address = os.path.join(project, folder)
file_address = os.path.join(folder_address, file)
os.mkdir(folder_address)

df = load_data()
frequency_cleaveland = pd.read_csv(
    "/home/aman/PycharmProjects/seasonality_hypothesis/data_generated/frequency_days_4200_C005.csv")
# bucket_1_sample = frequency_cleaveland[(frequency_cleaveland["frequency"] > 26) & (frequency_cleaveland["days"] > 730)].sample(400, random_state=1)
# bucket_1_sample.to_csv(
#     "/home/aman/PycharmProjects/seasonality_hypothesis/data_generated/bucket_1_sample.csv", index=False)
sample = frequency_cleaveland[(frequency_cleaveland["frequency"] < 12)
                              & (frequency_cleaveland["days"] > 112)]
print("Number of combos: ", sample.shape[0])
sample = sample.sample(400, random_state=1)
sample.to_csv(folder_address+"/sample.csv")
sample = pd.read_csv(folder_address+"/sample.csv")
report = pd.DataFrame()
count = 0
# start = time.time()
for index, row in sample.iterrows():
    kunag = int(row["kunag"])
    matnr = int(row["matnr"])
    try:
        test1 = ljung_box_test(df, matnr)
        test1_flag = test1[0]
        test1_pvalue = test1[1]
        aggregated_product = test1[4]
        test2 = dtw_check(df, kunag, matnr)
        test2_flag = test2[0]
        test2_value = test2[1]
    except:
        test1 = False
        test2 = False
    df_series = individual_series(df, kunag, matnr)
    if test1_flag:
        seasonality_component = product_seasonal_comp_7_point(df, matnr)
        result_52_seasonal = moving_average_with_seasonality(df_series, seasonality_component, order=52)
        result_52_nonseasonal = moving_average(df_series, order=52)
        # result = arima_rolling_011(df_series)
        # result_seasonal = arima_seasonality_added_rolling_011(df_series, seasonality_component)
        error_result_nonseasonal = pow(mean_squared_error(df_series["quantity"].iloc[-16:],
                                              result_52_nonseasonal["prediction"].iloc[-16:]), 0.5)
        error_result_seasonal = pow(mean_squared_error(df_series["quantity"].iloc[-16:],
                                                       result_52_seasonal["prediction"].iloc[-16:]), 0.5)
        report = report.append([[kunag, matnr, test1_flag, test1_pvalue, test2_flag, test2_value,
                                 error_result_nonseasonal, error_result_seasonal]])
        report.to_csv(file_address, index=False)
        count += 1
        print("count: ", count)
        df_series = df_series.set_index("dt_week")
        plt.figure(figsize=(16, 8))
        plt.subplot(311)
        plt.plot(df_series, marker=".", markerfacecolor="red", label="actual")
        plt.plot(result_52_nonseasonal.set_index("dt_week").iloc[-16:]["prediction"], marker=".", markerfacecolor="red",
                 label="order_52_" + str(error_result_nonseasonal))
        plt.plot(result_52_seasonal.iloc[-16:]["prediction"], marker=".", markerfacecolor="red",
                 label="order_52_seasonal_" + str(error_result_seasonal))
        plt.xlabel("Date", fontsize=14)
        plt.ylabel("Quantity", fontsize=14)
        plt.legend()
        plt.subplot(312)
        plt.plot(aggregated_product.set_index("dt_week")["quantity"], marker=".", markerfacecolor="red", label="aggregated")
        plt.xlabel("Date", fontsize=14)
        plt.ylabel("Quantity", fontsize=14)
        plt.legend()
        plt.subplot(313)
        print(seasonality_component)
        plt.plot(seasonality_component["quantity"], marker=".", markerfacecolor="red", label="seasonality")
        plt.xlabel("Date", fontsize=14)
        plt.ylabel("Quantity", fontsize=14)
        plt.legend()
        # plt.show()
        plt.title(str(test2_flag))
        plt.savefig(folder_address + "/" + str(test2_flag) + "_" + str(kunag) + "_" + str(matnr)+".png")
report.columns = ["kunag", "matnr", "test1_flag", "test1_pvalue", "test2_flag", "test2_value", "error_result",
                  "error_result_seasonal"]

# end = time.time()
# print("time consumed :", (end - start) / 60, " minutes")
report.to_csv(file_address, index=False)

"""
report = pd.read_csv(
    "/home/aman/PycharmProjects/seasonality_hypothesis/category_8/report.csv")
report["min_order"] = report.apply(lambda x: x.argmin(x), axis=1)
print(report["min_order"].value_counts())
"""


from django.db import models
from django.conf import settings
# Create your models here.

class Club(models.Model):
    name = models.CharField(
            max_length=50,
            verbose_name='club name',
        )
    image = models.ImageField(
            upload_to='club/%Y/%m/%d/',
            blank=True,
            null=True,
        )
    description = models.TextField(
            verbose_name='club description',
            blank=True,
            null=True,
        )

    def __str__(self):
        return self.name

class ApplyList(models.Model):
    club = models.ForeignKey(
            Club,
            on_delete=models.CASCADE,
        )
    user = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.CASCADE,
        )

    def __str__(self):
        return '{0} : {1}'.format(self.club, self.user)

class ClubRule(models.Model):
    main_theme = models.CharField(
            max_length=30,
            verbose_name='main theme',
        )
    sub_theme = models.CharField(
            max_length=30,
            verbose_name='sub theme',
            blank=True,
            null=True,
        )
    rule = models.TextField(verbose_name='rule')
    club = models.ForeignKey(
            Club,
            on_delete=models.CASCADE,
        )

    def __str__(self):
        return self.main_theme


class Solution:
    def taskAssignment(self, tasks, k):
        # Time O(nlog(n)) || Space O(n)
        if len(tasks) != k * 2:
            return []

        res = []
        taskDurationIdx = self.getTaskIdx(tasks)
        tasks.sort()
        for i in range(k):

            taskTime1 = tasks[i]
            allIdxTask1 = taskDurationIdx[taskTime1]
            currIdxTask1 = allIdxTask1.pop()

            idx2 = len(tasks) - 1 - i
            taskTime2 = tasks[idx2]
            allIdxTask2 = taskDurationIdx[taskTime2]
            currIdxTask2 = allIdxTask2.pop()

            res.append([currIdxTask1, currIdxTask2])

        return res

    def getTaskIdx(self, tasks):
        taskAndIdx = {}
        for idx, task in enumerate(tasks):

            if task not in taskAndIdx:
                taskAndIdx[task] = [idx]
            else:
                taskAndIdx[task].append(idx)

        return taskAndIdx

if __name__ == "__main__":

    print(Solution().taskAssignment([1, 3, 5, 3, 1, 4], 3))
    print(Solution().taskAssignment([1, 8, 9, 10], 2))
    print(Solution().taskAssignment([2, 1, 3, 4, 5, 13, 12, 9, 11, 10, 6, 7, 14, 8], 7))


# uncompyle6 version 3.7.4
# Python bytecode 3.7 (3394)
# Decompiled from: Python 3.6.9 (default, Apr 18 2020, 01:56:04)
# [GCC 8.4.0]
# Embedded file name: build/bdist.macosx-10.9-x86_64/egg/islatu/background.py
# Compiled at: 2020-04-21 10:49:38
# Size of source mod 2**32: 3530 bytes
"""
Background substraction is a necssary component of reflectometry reduction,
where the background scattering is removed from the reflected intensity.

Herein are some function to enable that for a two-dimensional detector image.
"""
import numpy as np
from scipy.stats import multivariate_normal
from scipy.optimize import curve_fit
from uncertainties import unumpy as unp

def bivariate_normal(data, mu_1, mu_2, sigma_1, sigma_2, offset, factor):
    """
    Produce a bivariate normal distribution.

    Note: the covariance of the two dimensions is assumed to be zero to
    unsure greater stability.

    Args:
        data (array_like): Two-dimensional abscissa data.
        mu_1 (float): Mean in dimension 0 (horizontal).
        mu_2 (float): Mean in dimension 1 (vertical).
        sigma_1 (float): Variance in dimension 0 (horizontal).
        sigma_2 (float): Variance in dimension 1 (vertical).
        offset (float): Offset from the 0 for the ordinate, this is the
            background level.
        factor (float): Multiplicative factor for area of normal distribution.

    Returns:
        (array_like): Flattened ordinate data for bivariate normal
            distribution.
    """
    pos = np.empty(data[0].shape + (2, ))
    pos[:, :, 0] = data[0]
    pos[:, :, 1] = data[1]
    binormal = multivariate_normal([mu_1, mu_2], [[sigma_1, 0], [0, sigma_2]])
    return offset + binormal.pdf(pos).flatten() * factor

def fit_gaussian_2d(image, image_e, p0=None, bounds=None):
    """
    Fit a two-dimensional Gaussian function with some ordinate offset to an
    image with an uncertainty and return the results, index of offset and
    vertical distribution width.

    Args:
        image (array_like): The data to fit the Gaussian to.
        image_e (array_like): The data uncertainty.
        p0 (list, optional): An initial guess at the parameters. Defaults to
        values based on the image.
        bounds (tuple_of_list, optional): Bounds for the fitting. Defaults to
        values based on the image.

    Returns:
        (tuple): tuple containing:
            - (np.ndarray): The results (with uncertainties) for each of the 6 parameters fit.
            - (int): The index of the offset.
            - (int): The index of the vertical distribution width.
    """
    if p0 is None:
        p0 = [image.shape[0] / 2,
         image.shape[1] / 2,
         1,
         1,
         image.min(),
         image.max()]
    if bounds is None:
        bounds = (0,
         [
          image.shape[0],
          image.shape[1],
          100,
          100,
          image.max(),
          image.max() * 10])
    abscissa = np.array(np.mgrid[0:image.shape[0]:1, 0:image.shape[1]:1])
    popt, pcov = curve_fit(bivariate_normal,
      abscissa,
      (image.flatten()),
      bounds=bounds,
      sigma=(image_e.flatten()),
      p0=p0,
      maxfev=(2000 * (len(p0) + 1)))
    p_sigma = np.sqrt(np.diag(pcov))
    return (unp.uarray(popt, p_sigma), 4, 2)


import math , time
from rechner_functions import *

print("Hello Hauke")

def clear():
    for i in range(30):
        print("                                                                                ")

Command = input("bitte Command eingeben : ")

LIST = Command.split(" ")

LIST[0] = LIST[0].lower()

#das hier ist nur das umwandeln nicht der Rechner
if LIST[0] == "umwandeln":
    ErGebnisse = []
    count = 0
    flächen = 0
    Längen = 0
    try:
        text = open(LIST[1],mode="r").readlines()
    except:
        print("Datei nicht Gefunden oder Angegeben")
        quit()
    for i in text:
        count += 1
        Werte2 = i.split(",")
        i = i.replace("\n","")
        Werte = i.split(",")
        if "^2" in Werte[1] or "^2" in Werte[2] or "a" in Werte[1] or "ha" in Werte[1] or "a" in Werte[2] or "ha" in Werte[2]:
            flächen += 1
            Werte[1] = Werte[1].replace("^2","")
            Werte[2] = Werte[2].replace("^2", "")
            s1 = 0
            s2 = 0

            #km
            if "km" in Werte[1] or "km" == Werte[1]:
                s1 = 7
            if "km" in Werte[2] or "km" == Werte[2]:
                s2 = 7

            #hektar
            if "ha" == Werte[1] or "ha" == Werte[1]:
                s1 = 6
            if "ha" == Werte[2] or "ha" == Werte[2]:
                s2 = 6

            #ar
            if "a" == Werte[1] or "a" == Werte[1]:
                s1 = 5
            if "a" == Werte[2] or "a" == Werte[2]:
                s2 = 5

            #meter
            if "m" == Werte[1] or "m" == Werte[1]:
                s1 = 4
            if "m" == Werte[2] or "m" == Werte[2]:
                s2 = 4

            #dezimeter
            if "dm" == Werte[1] or "dm" == Werte[1]:
                s1 = 3
            if "dm" == Werte[2] or "dm" == Werte[2]:
                s2 = 3

            #cm
            if "cm" == Werte[1] or "cm" == Werte[1]:
                s1 = 2
            if "cm" == Werte[2] or "cm" == Werte[2]:
                s2 = 2

            #mm
            if "mm" == Werte[1] or "mm" == Werte[1]:
                s1 = 1
            if "mm" == Werte[2] or "mm" == Werte[2]:
                s2 = 1

            schritte = s1 - s2

            if "-" in str(schritte):
                ergebnis = float(Werte[0])
                schritte = str(schritte).replace("-","")
                for b in range(int(schritte)):
                    ergebnis /= 100
                ErGebnisse.append("Nummer : " + str(count) + " , " + str(ergebnis) + Werte2[2])

            else:
                ergebnis = float(Werte[0])
                for b in range(int(schritte)):
                    ergebnis *= 100
                ErGebnisse.append("Nummer : " + str(count) + " , " + str(ergebnis) + Werte2[2])
            print("Ergebnis ist : " + str(ergebnis))
            clear()

        else:

            Längen += 1

            s1 = 0
            s2 = 0

            # km
            if "km" in Werte[1] or "km" == Werte[1]:
                s1 = 5
            if "km" in Werte[2] or "km" == Werte[2]:
                s2 = 5

            # meter
            if "m" == Werte[1] or "m" == Werte[1]:
                s1 = 4
            if "m" == Werte[2] or "m" == Werte[2]:
                s2 = 4

            # dezimeter
            if "dm" == Werte[1] or "dm" == Werte[1]:
                s1 = 3
            if "dm" == Werte[2] or "dm" == Werte[2]:
                s2 = 3

            # cm
            if "cm" == Werte[1] or "cm" == Werte[1]:
                s1 = 2
            if "cm" == Werte[2] or "cm" == Werte[2]:
                s2 = 2

            # mm
            if "mm" == Werte[1] or "mm" == Werte[1]:
                s1 = 1
            if "mm" == Werte[2] or "mm" == Werte[2]:
                s2 = 1

            schritte = s1 - s2

            if s2 == 5 and not s1 == 5:
                if schritte < 0:
                    schritte -= 2
                elif schritte > 0:
                    schritte += 2
                else:
                    schritte += 0

            if "-" in str(schritte):
                ergebnis = float(Werte[0])
                schritte = str(schritte).replace("-","")
                for b in range(int(schritte)):
                    ergebnis /= 10
                ErGebnisse.append("Nummer : " + str(count) + " , " + str(ergebnis) + Werte2[2])

            else:
                ergebnis = float(Werte[0])
                for b in range(int(schritte)):
                    ergebnis *= 10
                ErGebnisse.append("Nummer : " + str(count) + " , " + str(ergebnis) + Werte2[2])
            print("Ergebnis ist : " + str(ergebnis))
            clear()

    delete = open("Umgerechnete_Einheiten.txt", mode="w")
    delete.write("")
    delete.close()

    for i in ErGebnisse:
        output = open("Umgerechnete_Einheiten.txt", mode="a")
        output.write(str(i))
        output.close()

    clear()
    cdown = 6
    while not cdown == 0:
        print("  ------------------------------------------------------------------------------  ")
        print(str(count) + " Ergebnise wurden berechnent !")
        print(str(flächen) + " Flachen wurden berechnet !")
        print(str(Längen) + " Längen wurden berechnet !")
        print("Program endet in : " + str(cdown) + " Sekunden")
        print("  ------------------------------------------------------------------------------  ")
        time.sleep(1)
        cdown -= 1
        clear()
    quit()

elif LIST[0] == "rechner":
    values = input("bitte calculation eingeben ! ")
    List = get_Values(values)
    print(List)
    if not is_emty(List[1]):
        outputKlammern = listCalculation(List[1],1)
        print(outputKlammern)


import time
import numpy as np
from src.load_data import *
from src.GAT_test import *
from utils import accuracy
import argparse
import random

parser = argparse.ArgumentParser()
parser.add_argument('--no-cuda', action='store_true', default=False, help='Disables CUDA training.')
parser.add_argument('--seed', type=int, default=72, help='Random seed.')

args = parser.parse_args()
args.cuda = not args.no_cuda and torch.cuda.is_available()

random.seed(args.seed)
np.random.seed(args.seed)
torch.manual_seed(args.seed)
if args.cuda:
    torch.cuda.manual_seed(args.seed)

g, features, labels, train_mask, val_mask, test_mask = load_twitter_data()

# print(train_mask)
# print(val_mask)
# print(test_mask)

# create the model, 2 heads, each head has hidden size 8
net = GAT(g,
          in_dim=features.size()[1],
          hidden_dim=8,
          out_dim=9,
          num_heads=2)

# create optimizer
optimizer = torch.optim.Adam(net.parameters(), lr=1e-3)

if args.cuda:
    net.cuda()
    features = features.cuda()
    labels = labels.cuda()
    train_mask = train_mask.cuda()
    val_mask = val_mask.cuda()
    test_mask = test_mask.cuda()

# main loop
dur = []
for epoch in range(10000):
    if epoch >= 3:
        t0 = time.time()

    logits = net(features)
    logp = F.log_softmax(logits, 1)
    loss_train = F.nll_loss(logp[train_mask], labels[train_mask])
    acc_train = accuracy(logp[train_mask], labels[train_mask])

    optimizer.zero_grad()
    loss_train.backward()
    optimizer.step()

    if epoch >= 3:
        dur.append(time.time() - t0)

    output = net(features)
    logp_output = F.log_softmax(output, 1)
    loss_val = F.nll_loss(logp_output[val_mask], labels[val_mask])
    acc_val = accuracy(logp_output[val_mask], labels[val_mask])

    loss_test = F.nll_loss(logp_output[test_mask], labels[test_mask])
    acc_test = accuracy(logp_output[test_mask], labels[test_mask])

    print(
        "Epoch {:05d} | Train Loss {:.4f} | Train Acc {:.4f} | Val Acc {:.4f} | Test Acc {:.4f} | Time(s) {:.4f}".format(
            epoch, loss_train.item(), acc_train, acc_val, acc_test, np.mean(dur)))

    # print("Epoch {:05d} | Loss {:.4f} | Time(s) {:.4f}".format(
    #     epoch, loss.item(), np.mean(dur)))


import json
from pprint import pprint as pp
from json import JSONDecoder
import sys
import datetime
import db_utilities as dbu

# --------------------------------------------------------#
# Function to group the duplicate keys from JSON file     #
# This function is run first after opening the JSON file  #
# If this function is not run, python will not allow      #
# duplicate keys. The last item will be overwritten       #
#---------------------------------------------------------#
def join_duplicate_keys(ordered_pairs):
    d = {}
    for k, v in ordered_pairs:
        if k in d:
           if type(d[k]) == list:
               d[k].append(v)
           else:
               newlist = []
               newlist.append(d[k])
               newlist.append(v)
               d[k] = newlist
        else:
           d[k] = v
    return d

def getItemsParentLevel(lengthList,node):
    itemVar =""
    for i in range(0,lengthList):
        itemVar = d[i][node]
    return itemVar

def getItemsChildLevel(node1,node2):
    itemVar =""
    lengthList = len(d)
    for i in range(0,lengthList):
        itemVar = d[i][node1][node2]
    return itemVar

def getItemsChildLevel_List(lengthList,node1,node2,iterationVal):
    itemVar =""
    for i in range(0,lengthList):
        itemVar = d[i][node1][iterationVal][node2]
    return itemVar

def getItemsSubChildLevel(node1,node2,node3):
    itemVar =""
    lengthList = len(d)
    for i in range(0,lengthList):
        itemVar = d[i][node1][node2][node3]
    return itemVar

def getItemsSubChildLevel_List(lengthList,node1,node2,node3,iterationVal):
    itemVar =""
    for i in range(0,lengthList):
        itemVar = d[i][node1][node2][iterationVal][node3]
    return itemVar

# -------------- Function to get the project details -----------------------

def getProjectName():
    project_name = getItemsChildLevel("project","name")

def getProjectDetails():
    # Get the project level details from the json file
    project_name = getItemsChildLevel("project", "name")
    project_start_date = getItemsChildLevel("project", "start")
    project_end_date = getItemsChildLevel("project", "end")
    project_workdays = getItemsChildLevel("project", "workdays")
    project_budget = getItemsChildLevel("project", "budget")
    project_loc_street1 = getItemsSubChildLevel("project", "location", "street1")
    project_loc_street2 = getItemsSubChildLevel("project", "location", "street2")
    project_loc_city = getItemsSubChildLevel("project", "location", "city")
    project_loc_state = getItemsSubChildLevel("project", "location", "state")
    project_loc_postal = getItemsSubChildLevel("project", "location", "postal")
    project_loc_country = getItemsSubChildLevel("project", "location", "country")

    print(project_workdays)

    ## Update the details to the database temp
    connObj = dbu.getConn()
    # --------------------------------------------------------
    # First truncate the data from project and location table
    # --------------------------------------------------------
    LsqlQuery = "TRUNCATE TABLE TEMP.PROJECTS"
    dbu.executeQueryString(LsqlQuery,connObj)

    # --------------------------------------------------------
    # Insert data to project and location table
    # --------------------------------------------------------
    start_date = datetime.datetime.strptime(project_start_date,'%m%d%Y').date().strftime('%Y%m%d')
    end_date = datetime.datetime.strptime(project_end_date,'%m%d%Y').date().strftime('%Y%m%d')

    execSQL = "INSERT INTO TEMP.PROJECTS(NAME, WORKDAYS,BUDGET,LOCATION_NAME,START) VALUES (%s,%s,%s,%s,%s);"
    execData = (project_name, json.dumps(project_workdays),int(project_budget),project_loc_state,start_date)
    dbu.executeSQLData(execSQL,execData, connObj)
    connObj.close()

# -------------- Function to get the contractor details -----------------------
def getContractorDetails():
    lengthList = len(d)
    ## Update the details to the database temp
    connObj = dbu.getConn()
    #contractor_type = (type(d[lengthList -1]["contractors"]))
    for i in range(0,len(d[lengthList -1]["contractors"])):
        # Get the project level details from the json file
        contractor_name = d[lengthList-1]["contractors"][i]["name"]
        contractor_email = d[lengthList-1]["contractors"][i]["email"]
        contractor_phone = d[lengthList-1]["contractors"][i]["phone"]
        contractor_pcontact = d[lengthList-1]["contractors"][i]["primary_contact"]

        # --------------------------------------------------------
        # First truncate the data from project and location table
        # --------------------------------------------------------
        LsqlQuery = "TRUNCATE TABLE TEMP.CONTRACTORS"
        dbu.executeQueryString(LsqlQuery, connObj)

        # --------------------------------------------------------
        # Insert data to project and location table
        # --------------------------------------------------------
        execSQL = "INSERT INTO TEMP.CONTRACTORS(NAME,EMAIL,PHONE,PM_CONTACT) VALUES (%s,%s,%s,%s);"
        execData = (contractor_name,contractor_email, contractor_phone, contractor_pcontact)
        dbu.executeSQLData(execSQL, execData, connObj)

    connObj.close()

def writeActivitiesData_MultipleActivities():
    activityList = []
    connObj = dbu.getConn()

    node1 = "bundles"
    node2 = "activities"
    bundles_name = getItemsChildLevel(len(d), "bundles", "name")
    bundles_phases = getItemsChildLevel(len(d), "bundles", "phases")

    for i in range(0, len(item_activities)):
        activities_name = getItemsSubChildLevel_List(len(d),node1,node2,"name",i)
        activities_contractor = getItemsSubChildLevel_List(len(d), node1,node2, "contractor",i)
        activities_total_planned_hours = getItemsSubChildLevel_List(len(d),node1,node2, "total_planned_hours",i)
        activities_total_planned_units = getItemsSubChildLevel_List(len(d),node1,node2, "total_planned_units",i)
        activities_planned_start = getItemsSubChildLevel_List(len(d), node1,node2, "planned_start",i)
        activities_planned_end = getItemsSubChildLevel_List(len(d),node1,node2, "planned_end",i)
        activities_actual_start = getItemsSubChildLevel_List(len(d), node1,node2, "actual_start",i)
        activities_actual_end = getItemsSubChildLevel_List(len(d), node1,node2, "actual_end",i)
        activities_unit_name = d[len(d) -1]["bundles"]["activities"][i]["unit"]["name"]
        activities_material = getItemsSubChildLevel_List(len(d), "bundles", "activities", "material",i)

        # --------------------------------------------------------
        # Insert data to project and location table
        # --------------------------------------------------------
        planned_start = datetime.datetime.strptime(activities_planned_start, '%m%d%Y').date().strftime('%Y%m%d')
        planned_end = datetime.datetime.strptime(activities_planned_end, '%m%d%Y').date().strftime('%Y%m%d')
        actual_start = datetime.datetime.strptime(activities_actual_start, '%m%d%Y').date().strftime('%Y%m%d')
        actual_end = datetime.datetime.strptime(activities_actual_end, '%m%d%Y').date().strftime('%Y%m%d')
        prj_name = getProjectName()

        execSQL = "INSERT INTO TEMP.ACTIVITIES(NAME,CONTRACTOR_NAME,TOTAL_PLANNED_HOURS,PROJECT_NAME,TOTAL_PLANNED_UNITS,PLANNED_START,PLANNED_END,UNIT_NAME,ACTUAL_START,ACTUAL_END) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);"
        execData = (activities_name, activities_contractor, activities_total_planned_hours, prj_name,activities_total_planned_units,planned_start, planned_end, activities_unit_name, actual_start, actual_end)

        dbu.executeSQLData(execSQL, execData, connObj)

        print('#####################')
        print(execSQL)
        print(execData)
        print('writing values')
        print('Bundle Name : %s' %bundles_name)
        print('Bundle Phases : %s' %bundles_phases)
        print ('Activity Name : %s' %activities_name)
        print ('Activity Unit Name : %s' %activities_unit_name)
        print ('Activity Material: %s' %activities_material)
        print('#####################')

def getItems_MultiBundle_MultiActivity(node1,node2,node3,iterationVal_h,iterationVal_i):
    itemVar =""
    for i in range(0,len(d)):
        itemVar = d[i][node1][iterationVal_h][node2][iterationVal_i][node3]
        #print(itemVar)
    return itemVar

def writeActivitiesData_MultiBundles_MultipleActivities(bundle_item):
    activityList = []
    node1 = "bundles"
    node2 = "activities"
    ## Update the details to the database temp
    connObj = dbu.getConn()

    #write the values of bundles
    bundles_name = d[len(d) -1][node1][bundle_item]["name"]
    bundles_phases = d[len(d) -1][node1][bundle_item]["phases"]
    #L_item_activities = d[lengthList - 1]["bundles"][bundle_item]["activities"]
    for i in range(0, len(item_activities)):
       activities_name = getItems_MultiBundle_MultiActivity(node1, node2, "name", bundle_item,i)
       activities_contractor = getItems_MultiBundle_MultiActivity(node1, node2, "contractor",bundle_item, i)
       activities_total_planned_hours = getItems_MultiBundle_MultiActivity(node1, node2, "total_planned_hours",bundle_item, i)
       activities_total_planned_units = getItems_MultiBundle_MultiActivity(node1, node2, "total_planned_units",bundle_item, i)
       activities_planned_start = getItems_MultiBundle_MultiActivity(node1, node2, "planned_start",bundle_item, i)
       activities_planned_end = getItems_MultiBundle_MultiActivity(node1, node2, "planned_end",bundle_item, i)
       activities_actual_start = getItems_MultiBundle_MultiActivity(node1, node2, "actual_start",bundle_item, i)
       activities_actual_end = getItems_MultiBundle_MultiActivity(node1, node2, "actual_end",bundle_item, i)
       activities_unit_name = d[len(d)-1]["bundles"][bundle_item]["activities"][i]["unit"]["name"]
       activities_material = getItems_MultiBundle_MultiActivity(node1, node2, "material",bundle_item, i)

       print(activities_planned_start)

       # --------------------------------------------------------
       # First truncate the data from project and location table
       # --------------------------------------------------------
       # LsqlQuery = "TRUNCATE TABLE TEMP.PROJECTS"
       # dbu.executeQueryString(LsqlQuery, connObj)

       # --------------------------------------------------------
       # Insert data to project and location table
       # --------------------------------------------------------
       planned_start = datetime.datetime.strptime(activities_planned_start, '%m%d%Y').date().strftime('%Y%m%d')
       planned_end = datetime.datetime.strptime(activities_planned_end, '%m%d%Y').date().strftime('%Y%m%d')
       actual_start = datetime.datetime.strptime(activities_actual_start, '%m%d%Y').date().strftime('%Y%m%d')
       actual_end = datetime.datetime.strptime(activities_actual_end, '%m%d%Y').date().strftime('%Y%m%d')
       prj_name = getProjectName()

       execSQL = "INSERT INTO TEMP.ACTIVITIES(NAME,CONTRACTOR_NAME,TOTAL_PLANNED_HOURS,PROJECT_NAME,TOTAL_PLANNED_UNITS,PLANNED_START,PLANNED_END,UNIT_NAME,ACTUAL_START,ACTUAL_END) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);"
       execData = (
       activities_name, activities_contractor, activities_total_planned_hours, prj_name, activities_total_planned_units,
       planned_start, planned_end, activities_unit_name, actual_start, actual_end)
       dbu.executeSQLData(execSQL, execData, connObj)

       print('#####################-- MultiBundle-MultiActivity----')
       print(execSQL)
       print(execData)
       print('writing values')
       print('Bundle Name : %s' % bundles_name)
       print('Bundle Phases : %s' % bundles_phases)
       print('Activity Name : %s' % activities_name)
       print('Activity Unit Name : %s' % activities_unit_name)
       print('Activity Material: %s' % activities_material)
       print('#####################')

    connObj.close()
# -----------------------------------------------------------#
# This function is called when  bundles is a list  and
# activities  is dictionary                                #
#-----------------------------------------------------------#

def getwriteBundleList_DictActivity(node1,node2,node3,iterationVal):
    itemVar = ""
    for i in range(0, len(d)):
        itemVar = d[i][node1][iterationVal][node2][node3]
    return itemVar

def writeBundleList_DictActivity(bundle_item):
    connObj = dbu.getConn()
    print('I am entering fn writeBundleList_DictActivity(i) ---')
    bundles_name = d[len(d) -1]["bundles"][bundle_item]["name"]
    bundles_phases = d[len(d) -1]["bundles"][bundle_item]["phases"]

    activities_name = getwriteBundleList_DictActivity("bundles","activities","name",bundle_item)
    activities_contractor = getwriteBundleList_DictActivity("bundles","activities", "contractor",bundle_item)
    activities_total_planned_hours = getwriteBundleList_DictActivity("bundles","activities", "total_planned_hours",bundle_item)
    activities_total_planned_units = getwriteBundleList_DictActivity("bundles","activities", "total_planned_units",bundle_item)
    activities_planned_start = getwriteBundleList_DictActivity("bundles", "activities", "planned_start",bundle_item)
    activities_planned_end = getwriteBundleList_DictActivity("bundles","activities", "planned_end",bundle_item)
    activities_actual_start = getwriteBundleList_DictActivity("bundles","activities", "actual_start",bundle_item)
    activities_actual_end = getwriteBundleList_DictActivity("bundles","activities", "actual_end",bundle_item)
    activities_unit_name = d[len(d)-1]["bundles"][bundle_item]["activities"]["unit"]["name"]
    activities_material = getwriteBundleList_DictActivity("bundles","activities", "material",bundle_item)

    # --------------------------------------------------------
    # Insert data to project and location table
    # --------------------------------------------------------
    planned_start = datetime.datetime.strptime(activities_planned_start, '%m%d%Y').date().strftime('%Y%m%d')
    planned_end = datetime.datetime.strptime(activities_planned_end, '%m%d%Y').date().strftime('%Y%m%d')
    actual_start = datetime.datetime.strptime(activities_actual_start, '%m%d%Y').date().strftime('%Y%m%d')
    actual_end = datetime.datetime.strptime(activities_actual_end, '%m%d%Y').date().strftime('%Y%m%d')
    prj_name = getProjectName()

    execSQL = "INSERT INTO TEMP.ACTIVITIES(NAME,CONTRACTOR_NAME,TOTAL_PLANNED_HOURS,PROJECT_NAME,TOTAL_PLANNED_UNITS,PLANNED_START,PLANNED_END,UNIT_NAME,ACTUAL_START,ACTUAL_END) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);"
    execData = (activities_name, activities_contractor, activities_total_planned_hours, prj_name,activities_total_planned_units,planned_start, planned_end, activities_unit_name, actual_start, actual_end)
    dbu.executeSQLData(execSQL, execData, connObj)

    print('###############-- writeBundleList_DictActivity() --######')
    print('writing values')
    print('Bundle Name : %s' % bundles_name)
    print('Bundle Phases : %s' % bundles_phases)
    print('Activity Name : %s' % activities_name)
    print('Activity Unit Name : %s' % activities_unit_name)
    print('Activity Material: %s' % activities_material)
    print('#####################')

    connObj.close()

# -----------------------------------------------------------#
# This function is called when both bundles and activities   #
# are dictionaries                                           #
# There is going to be only one entry in the list            #
# So directly read the values i.e: one bundle, one activity  #
#------------------------------------------------------------#
def writeBundle_Activity():
    ## Update the details to the database temp
    connObj = dbu.getConn()

    bundles_name = getItemsChildLevel(len(d),"bundles","name")
    bundles_phases = getItemsChildLevel(len(d), "bundles", "phases")
    activities_name = getItemsSubChildLevel("bundles","activities","name")
    activities_contractor = getItemsSubChildLevel("bundles", "activities", "contractor")
    activities_total_planned_hours = getItemsSubChildLevel("bundles", "activities", "total_planned_hours")
    activities_total_planned_units = getItemsSubChildLevel("bundles", "activities", "total_planned_units")
    activities_planned_start = getItemsSubChildLevel("bundles", "activities", "planned_start")
    activities_planned_end = getItemsSubChildLevel("bundles", "activities", "planned_end")
    activities_actual_start = getItemsSubChildLevel("bundles", "activities", "actual_start")
    activities_actual_end = getItemsSubChildLevel("bundles", "activities", "actual_end")
    activities_unit_name = d[len(d)-1]["bundles"]["activities"]["unit"]["name"]
    activities_material = getItemsSubChildLevel("bundles", "activities", "material")

    # --------------------------------------------------------
    # First truncate the data from project and location table
    # --------------------------------------------------------
    #LsqlQuery = "TRUNCATE TABLE TEMP.PROJECTS"
    #dbu.executeQueryString(LsqlQuery, connObj)

    # --------------------------------------------------------
    # Insert data to project and location table
    # --------------------------------------------------------
    planned_start = datetime.datetime.strptime(activities_planned_start, '%m%d%Y').date().strftime('%Y%m%d')
    planned_end = datetime.datetime.strptime(activities_planned_end, '%m%d%Y').date().strftime('%Y%m%d')
    actual_start = datetime.datetime.strptime(activities_actual_start, '%m%d%Y').date().strftime('%Y%m%d')
    actual_end = datetime.datetime.strptime(activities_actual_end, '%m%d%Y').date().strftime('%Y%m%d')
    prj_name = getProjectName()

    execSQL = "INSERT INTO TEMP.ACTIVITIES(NAME,CONTRACTOR_NAME,TOTAL_PLANNED_HOURS,PROJECT_NAME,TOTAL_PLANNED_UNITS,PLANNED_START,PLANNED_END,UNIT_NAME,ACTUAL_START,ACTUAL_END) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);"
    execData = (activities_name,activities_contractor,activities_total_planned_hours,prj_name,activities_total_planned_units,planned_start,planned_end,activities_unit_name,actual_start,actual_end)
    print(execSQL)
    print(execData)
    dbu.executeSQLData(execSQL, execData, connObj)
    connObj.close()

    print('#####################')
    print('writing values')
    print('Bundle Name : %s' % bundles_name)
    print('Bundle Phases : %s' % bundles_phases)
    print('Activity Name : %s' % activities_name)
    print('Activity Unit Name : %s' % activities_unit_name)
    print('Activity Material: %s' % activities_material)
    print('#####################')

with open("structural_data.json") as f:
    # bundle all the duplicate keys into one
    d = json.load(f, object_pairs_hook=join_duplicate_keys)

print(d)
#print(type(d))

# Now read each value inside the bundle and the iteration value
# first get the length of the bundle
#length_of_bundles = len(d[0]["bundles"])
#length_of_items_inside_bundles = len(d[0]["bundles"])

# first get each item from the list
item_project = getItemsParentLevel(len(d),"project")
item_bundles = getItemsParentLevel(len(d),"bundles")
print('Bundle Type is :- %s' %type(item_bundles))

if type(item_bundles)== list:
    lengthList = len(d)
    for i in range(0,len(item_bundles)):
        item_activities = d[lengthList - 1]["bundles"][i]["activities"]
        #print(item_activities)
        #print(type(item_activities))

# --- get all the project details ---
getProjectDetails()
getContractorDetails()
# --------------------------------

#---------------------------------------------------------------
## Now get the values of the bundles
# first check if it is a list or dict
# if it is a dict, we directly read the values
# if it is a list, then we iterate through the list and read them

if type(item_bundles)== list:
    lengthList = len(d)
    for i in range(0,len(item_bundles)):
        # find out how many activities are there for the current bundle
        item_activities = d[lengthList - 1]["bundles"][i]["activities"]
        if type(item_activities)==list:
            # the current index of bundle is passed
            print('I am calling fn writeActivitiesData_MultiBundles_MultipleActivities() ---')
            writeActivitiesData_MultiBundles_MultipleActivities(i)
            print('I returned from writeActivitiesData_MultiBundles_MultipleActivities() ---')
        elif type(item_activities)==dict:
            print('I am in blist and adict')
            # get the total list of items of activities in bundles
            print('I am calling fn writeBundleList_DictActivity(i) ---')
            writeBundleList_DictActivity(i)
elif type(item_bundles)== dict:
    print('Item Bundles is a dictionary ---')
    item_activities = d[len(d)-1]["bundles"]["activities"]
    if type(item_activities)==list:
        print('Item activities is a List ---')
        print('Calling func. writeActivitiesData_MultipleActivities() ---')
        writeActivitiesData_MultipleActivities()
    elif type(item_activities)==dict:
        print('Item activities is a dictionary ---')
        print('Calling func. writeBundle_Activity() ---')
        writeBundle_Activity()
'''
def main(args):
    hello(args[1])

if __name__ == '__main__':
    main(sys.argv)
'''

## End of Program ###--------------