#!usr/bin/env python3

import argparse
import pandas as pd
import yaml
from keras.callbacks import TensorBoard, ModelCheckpoint
from keras.optimizers import Adadelta
from keras.utils.training_utils import multi_gpu_model
from time import time

from  model import unet, segnet, segunet, fastnet
from generator import data_gen_small

def argparser():
	# command line argments
	parser = argparse.ArgumentParser(description="Image segmentation")

	parser.add_argument("--model", required=True, choices=['unet', 'segnet', 'segunet', 'fastnet'], help="model to use")
	parser.add_argument("--save_dir", required=True, help="output directory")
	parser.add_argument("--train_list", required=True, help="file containing a list of train images (jpg)")
	parser.add_argument("--trainimg_dir", required=True, help="directory containing train images")
	parser.add_argument("--trainmsk_dir", required=True, help="directory containing groundtruth of train images")
	parser.add_argument("--val_list", required=True, help="file containing a list of val images (jpg)")
	parser.add_argument("--valimg_dir", required=True, help="directory containing train images")
	parser.add_argument("--valmsk_dir", required=True, help="directory containing groundtruth of val images")

	parser.add_argument("--initial_weights", type=str, default='', help="file containing initial weights to train upon")
	parser.add_argument("--verbose", type=int, default=1, choices=[0, 1], help="# of GPUs used for training")
	parser.add_argument("--gpus", type=int, default=1, help="# of GPUs used for training")
	parser.add_argument("--period", type=int, default=1, help="epoch period for checkpoint")
	# NOTE: batch_size is limited by memory available; start with a high number and keep decreasing until the program can run without memory issues
	# NOTE: batch_size * epoch_steps = # training samples
	parser.add_argument("--batch_size", default=10, type=int, help="batch size")
	# parser.add_argument("--epoch_steps", default=100, type=int, help="number of epoch step")
	# NOTE: 1 epoch = 1 forward pass + 1 backward pass on ALL training samples
	parser.add_argument("--n_epochs", default=10, type=int, help="number of epoch")
	# NOTE: If we have time to go through all the validation samples, keep 'val_steps' to number of val samples (though this requires a lot of time and the system looks to be stuck after every epoch)
	# NOTE: batch_size * val_steps = # validation samples
	# parser.add_argument("--val_steps", default=10, type=int, help="number of valdation step")
	parser.add_argument("--n_labels", default=20,type=int, help="Number of label")
	parser.add_argument("--input_shape", default=(256, 256, 3), help="Input images shape")
	parser.add_argument("--kernel", default=3, type=int, help="Kernel size")
	parser.add_argument("--pool", default=2, type=int, help="pooling and unpooling size")
	parser.add_argument("--output_mode", default="softmax", type=str, help="output activation")

	parser.add_argument("--lr", default=0.1, type=float, help="Initial learning rate")
	parser.add_argument("--rho", default=0.95, type=float, help="Adadelta decay factor")
	parser.add_argument("--decay", default=0.01, type=float, help="Decay rate of Initial learning rate")
	parser.add_argument("--epsilon", default=None, type=float, help="Adadelta fuzz factor. If None, defaults to K.epsilon()")

	loss_options = ['mean_squared_error', 'mean_absolute_error', 'mean_absolute_percentage_error', 'mean_squared_logarithmic_error', 'squared_hinge', 'hinge', 'categorical_hinge', 'logcosh', 'categorical_crossentropy', 'sparse_categorical_crossentropy', 'binary_crossentropy', 'kullback_leibler_divergence', 'poisson', 'cosine_proximity']
	parser.add_argument("--loss", default="categorical_crossentropy", choices=loss_options, help="loss function")
	# # TODO: optimizer options: sgd, rmsprop, adagrad, adadelta, adam, adamax, nadam
	# parser.add_argument("--optimizer", default="adadelta", type=str, help="oprimizer")
	metric_options = ['accuracy', 'binary_accuracy', 'categorical_accuracy', 'sparse_categorical_accuracy', 'top_k_categorical_accuracy', 'sparse_top_k_categorical_accuracy']
	parser.add_argument("--metrics", default='accuracy', choices=metric_options, help="metrics")

	args = parser.parse_args()

	return args

def main(args):
	# set the necessary list i.e. list of names of images to be read
	train_list = pd.read_csv(args.train_list, header=None)
	train_list_len = len(train_list)
	epoch_steps = int(train_list_len/args.batch_size)
	val_list = pd.read_csv(args.val_list, header=None)
	val_list_len = len(val_list)
	val_steps = int(val_list_len/args.batch_size)

	# set the necessary directories
	trainimg_dir = args.trainimg_dir
	trainmsk_dir = args.trainmsk_dir
	valimg_dir = args.valimg_dir
	valmsk_dir = args.valmsk_dir

	# Generate batch data for SGD
	# NOTE: This helps control the batch size for each training and validation set
	train_gen = data_gen_small(trainimg_dir, trainmsk_dir, train_list, args.batch_size, [args.input_shape[0], args.input_shape[1]], args.n_labels)
	val_gen = data_gen_small(valimg_dir, valmsk_dir, val_list, args.batch_size, [args.input_shape[0], args.input_shape[1]], args.n_labels)

	# Create a model
	if args.model == 'unet':
		model = unet(\
			args.input_shape, args.n_labels, args.kernel, \
			args.pool, args.output_mode, args.gpus)
	elif args.model == 'segnet':
		model = segnet(\
			args.input_shape, args.n_labels, args.kernel, \
			args.pool, args.output_mode, args.gpus)
	elif args.model == 'segunet':
		model = segunet(\
			args.input_shape, args.n_labels, args.kernel, \
			args.pool, args.output_mode, args.gpus)
	elif args.model == 'fastnet':
		model = fastnet(\
			args.input_shape, args.n_labels, args.kernel, \
			args.pool, args.output_mode, args.gpus)

	# Keras moodel summary
	print(model.summary())

	# TODO: Configure the model for training
	optimizer = Adadelta(lr=args.lr, rho=args.rho, epsilon=args.epsilon, decay=args.decay)
	model.compile(loss=args.loss, optimizer=optimizer, metrics=[args.metrics])
	# model.compile(loss=args.loss, optimizer=args.optimizer, metrics=[args.metrics])

	# If pre-trained weights available, use those
	if(args.initial_weights):
		model.load_weights(args.initial_weights)
		print('Initial weights loaded')

	# Generate log for tensorboard (currently only useful parameters are added to the dir name)
	log_dir = args.save_dir + \
		'model_' + args.model + \
		'_batch_size_' + str(args.batch_size) + \
		'_epoch_steps_' + str(epoch_steps) + \
		'_n_epochs_' + str(args.n_epochs) + \
		'_lr_' + str(args.lr) + \
    	'_decay_' + str(args.decay) + \
    	'_labels_' + str(args.n_labels) + \
    	'/'
	tensorboard = TensorBoard(log_dir=log_dir)

	# Generate checkpoints
	checkpoint = ModelCheckpoint(log_dir+'weights_at_epoch_{epoch:03d}.hdf5', verbose=1, save_best_only=False, save_weights_only=True, period=args.period) # Create 10 checkpoints only

	# Train the model on data generated batch-by-batch by a Python generator
	# NOTE: We use fit_generator because we do provide our generated dataset with specific batch size
	fit_start_time = time()
	model.fit_generator(train_gen, steps_per_epoch=epoch_steps, epochs=args.n_epochs, validation_data=val_gen, validation_steps=val_steps, verbose=args.verbose, callbacks=[checkpoint, tensorboard])
	print('### Model fit time (s): ', time()-fit_start_time)

	# # NOTE: Cannot save the whole model OR the model structure if the model is not Keras Sequential, it throws "AttributeError: 'NoneType' object has no attribute 'update'"
	# # This is a bug in Keras (not sure about TensorFlow)
	# # Therefore, the model strutuce must be generated every time it is required to be implemented outside of the current script
	# model.save(log_dir + 'model.hdf5') # Model architecture and final weights

	# Save final weights
	model.save_weights(log_dir + 'weights_at_epoch_%03d.hdf5' % (args.n_epochs))
	print('Final model weights saved.')

if __name__ == "__main__":
	program_start_time = time()
	args = argparser()
	main(args)
	print('### Whole program time (s): ', time()-program_start_time)


import re
import time

from collections import Counter

start_time = time.time()

def solve(filename):
    with open(filename) as f:
        lines = f.read().strip().splitlines()
    intervals = [tuple(map(int, re.findall('-?\d+', line))) for line in lines]
    intervals = [{'center': x[0], 'radius': x[1]} for x in intervals]
    for inter in intervals:
        inter['lower'] = inter['center'] - inter['radius']
        inter['upper'] = inter['center'] + inter['radius']

    lowers = [inter['lower'] for inter in intervals]
    uppers = [inter['upper'] for inter in intervals]
    after_uppers = [u+1 for u in uppers]

    lower_counts = Counter(lowers)
    upper_counts = Counter(uppers)
    after_upper_counts = Counter(after_uppers)
    all_events = sorted(set(lowers + after_uppers))
    summaries = []
    value = 0
    last_change = None
    for evt in all_events:
        change = lower_counts[evt] - after_upper_counts[evt]
        if last_change is not None:
            summaries.append(((last_change, evt-1), value))
        value += change
        last_change = evt

    max_overlaps = max(summaries, key=lambda x: x[1])[1]
    max_intervals = [s for s in summaries if s[1] == max_overlaps]

    # We will take a point in one of the max_intervals, and verify that it really does lie in max_overlaps

    point = float('inf')
    for inter in max_intervals:
        lower, upper = inter[0]
        if lower <= 0 <= upper:
            point = 0
        else:
            if abs(lower) < abs(point):
                point = lower
            if abs(upper) < abs(point):
                point = upper

    count = 0
    for inter in intervals:
        if inter['lower'] <= point <= inter['upper']:
            count += 1
    print("Largest overlap from algorithm:", max_overlaps)
    print("Verified that {} is contained in {} intervals".format(point, count))

def main():
    solve('squares1.txt')

if __name__ == "__main__":
    main()


#!/usr/bin/env python

import os

# Import custom modules from the above directory
import iclrt_tools.plotting.dfplots as df
import iclrt_tools.data_sets.waveforms as wvf
import iclrt_tools.filters.filters as filters

# Import other modules
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt

import pickle
import operator

import xml.etree.ElementTree as et

class DataSet(object):

    def __init__(self, xml_file):
        self.xml_file = xml_file

        # Get information from XML file
        self.root = et.parse(self.xml_file)

        day = self.root.find('date').find('day').text
        month = self.root.find('date').find('month').text
        year = self.root.find('date').find('year').text[-2:]

        self.eventDate = '%s%s%s' % (month, day, year)
        self.eventName = self.root.find('name').text
        self.eventNamef = "%s%s%s" % (self.eventName[0:2],
                                      self.eventName[3:5],
                                      self.eventName[6:])

    def get_data_set(self, rs='all', meass='all'):
        os.chdir('/home/jaime/Documents/ResearchTopics/Publications/Current Reflections/Data Sets/')
        mpl.rcParams['figure.dpi'] = 150

        self.data = {}
        # self.rt_plots = {}

        """
        Get data for each scope
        """
        print("Event: %s" % self.eventName)
        print("Date : %s" % self.eventDate)

        for rss in self.root.iter('return_stroke'):
            r_s = int(rss.find('number').text)

            if 'all' in rs.lower():
                pass
            elif r_s == int(rs):
                pass
            else:
                continue

            print("\nRS   : #%d" % r_s)

            fileSave = "./DataFiles/%s_data_%s_rs%d.p" % (self.eventNamef,
                                                             self.eventDate,
                                                             r_s)

            self.saved_keys = []
            self.fo = None

            if not("all" in meass.lower()):
                try:
                    self.fo = pickle.load(open(fileSave, "rb"))
                    self.saved_keys = self.fo.keys()

                except FileNotFoundError:
                    pass

            for scope in rss.iter('scope'):
                scope_data = {}

                scope_name = scope.find('name').text
                scope_type = scope.find('type').text
                scope_path = scope.find('path').text

                for measurement in scope.iter('measurement'):
                    if self.saved_keys:
                        if "all" in meass.lower():
                            pass
                        elif meass in measurement.find('name').text:
                            pass
                        else:
                            continue

                    measurement_name = measurement.find('name').text
                    file_name = '{path}/{file}'.format(path=scope_path,
                                file=measurement.find('file').text)
                    trace = int(measurement.find('trace').text)
                    cal_factor = float(measurement.find('cal_factor').text)
                    units = measurement.find('units').text
                    distance = float(measurement.find('distance').text)
                    t_start = float(measurement.find('t_start').text)
                    t_end = float(measurement.find('t_end').text)

                    meas = wvf.Waveform(flash_name=self.eventName,
                                        event_date=self.eventDate,
                                        return_stroke=r_s,
                                        measurement_name=measurement_name,
                                        scope_name=scope_name,
                                        scope_type=scope_type,
                                        file_name=file_name,
                                        trace_number=trace,
                                        cal_factor=cal_factor,
                                        units=units, distance=distance,
                                        t_start=t_start, t_end=t_end)

                    print(meas)

                    scope_data[measurement_name] = meas

                self.data.update(scope_data)

        for key in self.data:
            print("Acquiring {meas}...".format(meas=key))
            self.data[key].get_data()

        self.save_data(fileSave)

    def plot_data_set(self, rs='all', meass='all', lim=20, window=1.0,
                      norm=False):
        #~ mpl.rcdefaults()
        os.chdir('/home/jaime/Documents/ResearchTopics/Publications/Current Reflections/Data Sets/')

        for rss in self.root.iter('return_stroke'):

            r_s = int(rss.find('number').text)

            if rs == -1:
                pass
            elif 'all' in rs.lower():
                pass
            elif r_s == int(rs):
                pass
            else:
                continue

            fileSave = "./DataFiles/%s_data_%s_rs%d.p" % (self.eventNamef,
                                                             self.eventDate,
                                                             r_s)

            data = pickle.load(open(fileSave, "rb"))

            data_only = {}

            if "all" in meass:
                ignore = []
                E = ['E_5', 'E_18', 'E_23', 'E_12F', 'E_12', 'E_NW60',
                     'E_NW100']
                dE = ['dE_1', 'dE_3', 'dE_4', 'dE_5', 'dE_7', 'dE_8', 'dE_9', 'dE_11', 'dE_17', 'dE_25', 'dE_OB']
                intt = ['intE_1', 'intE_3', 'intE_4', 'intE_5', 'intE_7', 'intE_8', 'intE_9', 'intE_11', 'intE_17', 'intE_25', 'intE_OB']

                ignore.extend(intt)
                ignore.extend(E)
                ignore.extend(['II_HI'])
                # ignore.extend(dE)

                for key in data:
                    if key in ignore:
                        pass
                    else:
                        data_only[key] = data[key]

                keys = data_only.keys()
                sort_data = {}

                for i, key in enumerate(keys):
                    value = data[key].ax.get_title().split()

                    if len(value) == 4:
                        s = value[3]
                        ind = s.find('km')

                        if ind > 0:
                            temp = float(value[3][:ind])
                            s = '%d' % (temp*1E3)

                        ind = s.find('m')

                        if ind > 0:
                            s = value[3][:ind]

                        sort_data[key] = float(s)

                    else:
                        s = value[4]
                        ind = s.find('km')

                        if ind > 0:
                            temp = float(value[4][:ind])
                            s = '%d' % (temp*1E3)

                        ind = s.find('m')

                        if ind > 0:
                            s = value[4][:ind]

                        sort_data[key] = float(s)

                sorted_data = sorted(sort_data.items(),
                                     key=operator.itemgetter(1))

                """
                Print all in individual figures
                """
                mpl.rcParams['savefig.directory'] = '/home/jaime/Documents/My Papers/Ongoing/Current Reflections/LaTex/Pictures/Temp/'

                for i in range(len(sorted_data)):

                    fig, ax = plt.subplots(1, 1)

                    #~ fig.suptitle('%s (%s/%s/%s)' % (event, eventDate[:2],eventDate[2:4], eventDate[4:]), fontsize=16)
                    #~ fig.suptitle(event)#, fontsize=16)

                    temp_data = data[sorted_data[i][0]].data

                    # print(sorted_data[i], len(data[sorted_data[i][0]]), len(temp_data), len(data['time']), np.max(temp_data))

                    zoom_lim = [-1, int(lim)]

                    # print(zoom_lim)

                    factor = 1E-3
                    l_width = 2.5

                    if 'dE_' in sorted_data[i][0]:
                        factor = 1E-9
                        l_width = 1.5

                    ax.plot(data[sorted_data[i][0]].dataTime, factor*temp_data,
                            linewidth=l_width)
                    ax.set_title(data[sorted_data[i][0]].ax.get_title())

                    if "ii_hi" in sorted_data[i][0].lower():
                        ylabel = '(kA)'

                    elif "int" in sorted_data[i][0].lower():
                        ylabel = '(kV/m)'

                    elif "de" in sorted_data[i][0].lower():
                        ylabel = '(kV/m/$\mu$s)'

                    elif "e_" in sorted_data[i][0].lower():
                        ylabel = '(kV/m)'

                    else:
                        ylabel = data[sorted_data[i][0]].ax.get_ylabel()

                    if '/us' in ylabel:
                        ylabel = ylabel[:-3] + ylabel[-1]

                    #~ ax.set_ylabel(ylabel)
                    ax.set_xlim(zoom_lim)
                    ax.xaxis.set_minor_locator(mpl.ticker.AutoMinorLocator())
                    ax.grid(True, which='both')
                    ax.xaxis.set_tick_params(width=1.5)
                    #~ ax.autoscale(True,'y')
                    #~ ax.set_xlabel('Time ($\mu$s)')

                    p = df.pickerPlot(fig, ax)
                    p.plot()

            else:
                mpl.rcParams['savefig.directory'] = '/home/jaime/Documents/My Papers/Ongoing/Current Reflections/LaTex/Pictures/Temp/'

                x = data[meass].dataTime
                y = data[meass].data

                y_filtered = filters.moving_average(y, window)

                #~ plt.plot(x, y, '-', x,y_filtered, '--')

                norm_factor = 1.0
                factor = 1E-3
                l_width = 2.5

                if 'dE_' in meass:
                    factor = 1E-9
                    l_width = 1.5

                ### Normalize waveform
                if norm:
                    p = df.RelativeTimePlot(x,y)
                    p.plot()

                    plt.show()

                    zero = y[p.zero_ind]

                    p = df.RelativeTimePlot(x, y)
                    p.plot()

                    plt.show()

                    peak = y[p.zero_ind]

                    norm_factor = float(peak - zero)*factor

                fig = plt.figure()
                ax = fig.add_subplot(111)

                zoom_lim = [-1, int(lim)]

                title = '%s (RS #%d)' % (self.eventName, r_s)
                # title = '%s (ICC)' % self.eventName
                # title = data[meass].ax.get_title()

                # if factor == 1E-3:
                #     ylabel = '(k%s' % (data[meass].ax.get_ylabel()[1:])
                # else:
                #     ylabel = data[meass].ax.get_ylabel()

                xlabel = 'Time ($\mu$s)'

                ax.plot(x*1e6, y_filtered*factor/norm_factor, linewidth=l_width)
                ax.set_title(title)
                #~ ax.set_ylabel(ylabel)
                #~ ax.set_xlabel(xlabel)
                ax.xaxis.set_minor_locator(mpl.ticker.AutoMinorLocator())
                ax.grid(True, which='both')
                ax.xaxis.set_tick_params(width=1.5)
                #~ ax.autoscale(True,'y')
                ax.set_xlim(zoom_lim)
                #~ ax.yaxis.set_minor_locator(mpl.ticker.AutoMinorLocator())

                p = df.pickerPlot(fig, ax)
                p.plot()

            plt.show()

    def save_data(self, fileSave):
        os.chdir('/home/jaime/Documents/ResearchTopics/Publications/Current Reflections/Data Sets/')
        print("Saving data to: {file}".format(file=fileSave))
        if self.data:
            if self.fo:
                file_data = self.fo
                file_data.update(self.data)
            else:
                file_data = self.data

            pickle.dump(file_data, open(fileSave, "wb"))

    def print_keys(self, rs='all'):
        os.chdir('/home/jaime/Documents/ResearchTopics/Publications/Current Reflections/Data Sets/')

        for rss in self.root.iter('return_stroke'):

            r_s = int(rss.find('number').text)

            if rs == -1:
                pass
            elif 'all' in rs.lower():
                pass
            elif r_s == int(rs):
                pass
            else:
                continue

            fileSave = "./DataFiles/%s_data_%s_rs%d.p" % (self.eventNamef,
                                                          self.eventDate, r_s)
            data = pickle.load(open(fileSave, "rb"))

            event = '%s RS #%d:' % (self.eventName, r_s)

            keys = data.keys()

            print(event)

            for key in keys:
                if not(key in ignore):
                    print('    ' + key)
            print()

    def calc_rise(self, rs='all', meass='all'):
        os.chdir('/home/jaime/Documents/ResearchTopics/Publications/Current Reflections/Data Sets/')
        for rss in self.root.iter('return_stroke'):

            r_s = int(rss.find('number').text)

            if rs == -1:
                pass
            elif 'all' in rs.lower():
                pass
            elif r_s == int(rs):
                pass
            else:
                continue

            fileSave = "./DataFiles/%s_data_%s_rs%d.p" % (self.eventNamef,
                                                             self.eventDate,
                                                             r_s)
            data = pickle.load(open(fileSave, "rb"))

            event = '%s RS%d' % (self.eventName, r_s)

            keys = data.keys()

            if meass in keys:

                ii = data[meass].data
                time = data[meass].dataTime*1.0E-6

                fig, ax = plt.subplots(1,1)
                ax.plot(time, ii)
                plt.title('Get Noise Only')

                p = df.plotdf(fig, ax)
                p.plot()
                plt.show()

                y = p.ax.get_lines()[0].get_ydata()

                mean = np.mean(y)
                std = np.std(y)
                three_sigma = 3*std

                fig, ax = plt.subplots(1,1)
                ax.plot(time, ii - mean)
                plt.title('Select rise only')

                p = df.plotdf(fig, ax)
                p.plot()
                plt.show()

                y = p.ax.get_lines()[0].get_ydata()
                # y -= mean

                t = p.ax.get_lines()[0].get_xdata()

                peak = np.max(y)
                amp = peak - three_sigma

                t_start = np.argmax(np.abs(1.0/(0.1*amp + three_sigma - y)))
                t_end = np.argmax(np.abs(1.0/(0.9*amp + three_sigma - y)))

                rise_time = (t[t_end] - t[t_start])*1.0E9

                tt_start = np.argmax(np.abs(1.0/(three_sigma - y)))

                ind1 = np.where(time == t[tt_start])
                ind2 = np.where(time == t[t_start])
                ind3 = np.where(time == t[t_end])

                time *= 1.0E9

                fig = plt.figure()
                ax = fig.add_subplot(111)
                ax.plot(time, ii - mean, '-x')
                ax.plot(time[ind2],ii[ind2], 'ro')
                ax.plot(time[ind3], ii[ind3], 'ro')
                ax.set_title('Peak and Risetime')

                ylims = plt.gca().get_ylim()
                ax.plot([time[ind1], time[ind1]], [ylims[0], ylims[1]],
                         '--r', linewidth=1.0)
                ax.plot([time[ind2], time[ind2]], [ylims[0], ylims[1]],
                         '--r', linewidth=1.0)
                ax.plot([time[ind3], time[ind3]], [ylims[0], ylims[1]],
                         '--r', linewidth=1.0)

                xlims = plt.gca().get_xlim()
                ax.plot([xlims[0],xlims[1]], [ii[ind2],ii[ind2]],
                         '--r', linewidth=1.0)
                ax.plot([xlims[0],xlims[1]], [ii[ind3],ii[ind3]],
                         '--r', linewidth=1.0)

                ax.plot([xlims[0],xlims[1]], [0,0],
                         '--k', linewidth=1.0)
                ax.plot([xlims[0],xlims[1]], [three_sigma,three_sigma],
                         '--g', linewidth=1.0)

                plt.text((xlims[-1] - xlims[0])/2 + xlims[0],(ylims[-1] - ylims[0])/2 + ylims[0]+1000, 'Peak = %0.2f kA' % ((peak)*1.0E-3))
                plt.text((xlims[-1] - xlims[0])/2 + xlims[0],(ylims[-1] - ylims[0])/2 + ylims[0], 'Risetime = %0.2f ns' % rise_time)

                ax.set_xlim([0,30E-6*1E9])

                print('RS # %d => %s: %0.2f A %0.2f ns' % (r_s, meass, peak,
                                                            rise_time))

                p = df.plotdf(fig, ax)
                p.plot()

                plt.show()

    def calc_dip_time(self, rs='all', meass='all', window=1.0):
        os.chdir('/home/jaime/Documents/ResearchTopics/Publications/Current Reflections/Data Sets/')

        for rss in self.root.iter('return_stroke'):

            r_s = int(rss.find('number').text)

            if rs == -1:
                pass
            elif 'all' in rs.lower():
                pass
            elif r_s == int(rs):
                pass
            else:
                continue

            fileSave = "./DataFiles/%s_data_%s_rs%d.p" % (self.eventNamef,
                                                          self.eventDate,
                                                          r_s)
            data = pickle.load(open(fileSave, "rb"))

            event = '%s RS%d' % (self.eventName, r_s)

            keys = data.keys()

            if meass in keys:

                ii = data[meass].data
                # ii = self.moving_average(ii, window)
                time = data[meass].dataTime*1.0E-6

                fig, ax = plt.subplots(1, 1)
                ax.plot(time, ii)
                plt.title('Get Noise Only')

                p = df.plotdf(fig, ax)
                p.plot()
                plt.show()

                y = p.ax.get_lines()[0].get_ydata()

                mean = np.mean(y)
                std = np.std(y)
                three_sigma = mean + 2*std

                fig, ax = plt.subplots(1,1)
                ax.plot(time, ii)
                plt.title('Get Rise Only')

                p = df.plotdf(fig, ax)
                p.plot()
                plt.show()

                y = p.ax.get_lines()[0].get_ydata()
                y -= mean

                t = p.ax.get_lines()[0].get_xdata()

                peak = np.max(y)
                amp = peak - three_sigma

                ind_ten = np.argmax(np.abs(1.0/(0.1*amp + three_sigma - y)))
                ind_ninety = np.argmax(np.abs(1.0/(0.9*amp + three_sigma - y)))

                ind_start = np.argmax(np.abs(1.0/(three_sigma - y)))
                t_start = t[ind_start]
                t_max = t[np.argmax(y)]

                t_ten = t[ind_ten]
                t_ninety = t[ind_ninety]

                fig, ax = plt.subplots(1,1)
                ax.plot(time, ii)
                plt.title('Get Dip Only')

                p = df.plotdf(fig, ax)
                p.plot()
                plt.show()

                y = p.ax.get_lines()[0].get_ydata()
                y -= mean

                t = p.ax.get_lines()[0].get_xdata()

                amp = np.max(y) - np.min(y)
                dip_peak = amp

                ind_end = 0
                t_end = t[ind_end]
                t_min = t[np.argmin(y)]

                ind1 = np.where(time == t_start)
                ind2 = np.where(time == t_end)
                ind3 = np.where(time == t_max)
                ind4 = np.where(time == t_min)

                risetime = t_ninety - t_ten

                delay = t_end - t_start
                delay1 = t_min - t_max

                plt.plot(time*1E6, ii - mean)
                ylims = plt.gca().get_ylim()
                plt.plot([time[ind1]*1E6, time[ind1]*1E6],
                         [ylims[0], ylims[1]],'r')
                plt.plot([time[ind2]*1E6, time[ind2]*1E6],
                         [ylims[0], ylims[1]], 'r')
                plt.plot([time[ind3]*1E6, time[ind3]*1E6],
                         [ylims[0], ylims[1]], 'g')
                plt.plot([time[ind4]*1E6, time[ind4]*1E6],
                         [ylims[0], ylims[1]], 'g')

                xlims = plt.gca().get_xlim()
                plt.plot([xlims[0],xlims[1]], [0,0],
                         '--k', linewidth=1.0)
                plt.plot([xlims[0],xlims[1]],
                         [three_sigma - mean, three_sigma - mean],
                         '--g', linewidth=1.0)

                plt.text(time[ind1]*1E6,0, '%0.2f (us)' % (delay*1E6), color='red')
                plt.text(time[ind4]*1E6,0, '%0.2f (us)' % (delay1*1E6), color='green')
                plt.xlim([0,30])

                print('RS # %d => Peak: %0.2f (kA)' % (r_s, peak*1E-3))
                print('RS # %d => Risetime: %0.2f (ns)' %
                      (r_s, risetime*1.0E9))
                print('RS # %d => Dip Peak: %0.2f (kA)' %
                      (r_s, dip_peak*1E-3))
                print('RS # %d => Dip Delay start to start: %0.2f (us)' %
                      (r_s, delay*1E6))
                print('RS # %d => Dip Delay peak to dip: %0.2f (us)' %
                      (r_s, delay1*1E6))
                plt.show()

    def calc_dip(self,rs='all', meass='all', window=1.0):
        os.chdir('/home/jaime/Documents/ResearchTopics/Publications/Current Reflections/Data Sets/')

        for rss in self.root.iter('return_stroke'):

            r_s = int(rss.find('number').text)

            if rs == -1:
                pass
            elif 'all' in rs.lower():
                pass
            elif r_s == int(rs):
                pass
            else:
                continue

            fileSave = "./DataFiles/%s_data_%s_rs%d.p" % (self.eventNamef,
                                                          self.eventDate, r_s)
            data = pickle.load(open(fileSave, "rb"))

            event = '%s RS%d' % (self.eventName, r_s)

            keys = data.keys()

            if meass in keys:

                # ii = self.moving_average(data[meass].data, window)
                ii = data[meass].data
                time = data[meass].dataTime*1.0E-6

                fig, ax = plt.subplots(1,1)
                ax.plot(time, ii)
                plt.title('Calculate Dip')

                p = df.plotdf(fig, ax)
                p.plot()
                plt.show()

                y = p.ax.get_lines()[0].get_ydata()
                #~ y -= np.average(y[:20])

                time = p.ax.get_lines()[0].get_xdata()

                t_max = np.argmax(y)
                t_min = np.argmin(y)

                amp = np.max(y) - np.min(y)

                time *= 1E9

                plt.plot(time,y, '-x')
                plt.plot(time[t_max], y[t_max], 'ro')
                plt.plot(time[t_min], y[t_min], 'ro')
                plt.title('Dip')

                ylims = plt.gca().get_ylim()
                plt.plot([time[t_max], time[t_max]], [ylims[0], ylims[1]], 'r')
                plt.plot([time[t_min], time[t_min]], [ylims[0], ylims[1]], 'r')

                xlims = plt.gca().get_xlim()
                plt.plot([xlims[0],xlims[1]], [y[t_max],y[t_max]], 'r')
                plt.plot([xlims[0],xlims[1]], [y[t_min],y[t_min]], 'r')
                plt.text((xlims[-1] - xlims[0])/2 + xlims[0],(ylims[-1] - ylims[0])/2 + ylims[0], 'Peak = %0.2f kA' % (amp*1.0E-3))

                plt.show()

                print('RS # %d => %s: %0.2f kA' % (r_s, meass, amp*1E-3))


#!/usr/bin/env python

import i3ipc

def cycle(i3):
    wins = i3.get_tree().find_focused().workspace().leaves()
    focused = next(filter(lambda w: w[1].focused, enumerate(wins)))
    after = wins[(focused[0] + 1) % len(wins)]
    i3.command("[con_id={}] focus".format(after.id))

def main():
    i3 = i3ipc.Connection()
    cycle(i3)

if __name__ == "__main__":
    main()


import os
import glob
from conans import ConanFile, tools

class NanobenchConan(ConanFile):
    name = "nanobench"
    description = """ankerl::nanobench is a platform independent
                     microbenchmarking library for C++11/14/17/20."""
    topics = ("conan", "nanobench", "benchmark", "microbenchmark")
    url = "https://github.com/conan-io/conan-center-index"
    homepage = "https://github.com/martinus/nanobench"
    license = "MIT"
    no_copy_source = True

    @property
    def _source_subfolder(self):
        return "source_subfolder"

    def source(self):
        tools.get(**self.conan_data["sources"][self.version])
        extracted_dir = glob.glob(self.name + "-*/")[0]
        os.rename(extracted_dir, self._source_subfolder)

    def package(self):
        include_folder = os.path.join(
            self._source_subfolder, os.path.join("src", "include"))
        self.copy(pattern="LICENSE", dst="licenses",
                  src=self._source_subfolder)
        self.copy(pattern="*.h", dst="include", src=include_folder)

    def package_id(self):
        self.info.header_only()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: AlphaFF
# @Date:   2018-08-10 10:38:40
# @Email: liushahedi@gmail.com
# @Last Modified by:   AlphaFF
# @Last Modified time: 2018-08-10 11:00:12

from datetime import timedelta

# 使用Redis作为消息代理
BROKER_URL = 'redis://localhost:6379/0'
# 把任务结果存在了Redis
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
# 任务序列化和反序列化使用JSON方案
CELERY_TASK_SERIALIZER = 'json'
# 读取任务结果使用JSON
CELERY_RESULT_SERIALIZER = 'json'
# 任务过期时间，不建议直接写86400，应该让这样的magic数字表述更明显
CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24
# 指定接受的内容类型，是个数组，可以写多个
CELERY_ACCEPT_CONTENT = ['json']

CELERYBEAT_SCHEDULE = {
    'add': {
        'task': 'tasks.add',
        'schedule': timedelta(seconds=10),
        'args': (16, 16)
    }
}


import pygame
import sys
import pickle
from Client_Modules.networking import Network
from Client_Modules.pong import Pong
from Client_Modules.battleships import Battleships
from Client_Modules.papersoccer import PaperSoccer
from Client_Modules.flappybird import FlappyBird
from Client_Modules.race import Race
from Client_Modules.snakes import Snakes
from Client_Modules.bomberman import Bomberman
from Client_Modules.volleyball import Volleyball
from socket import error as SockError
from socket import timeout as SockTimeout

def main():

    pygame.init()
    pygame.font.init()
    restart = True
    net = Network()
    games = [Pong,Battleships, PaperSoccer, FlappyBird, Snakes, Bomberman, Volleyball, Race]
    game_names = ["Pong", "Battleships", "PaperSoccer", "FlappyBird", "Snakes", "Bomberman", "Volleyball", "Race"]
    screen = pygame.display.set_mode((1280, 960))
    clock = pygame.time.Clock()
    font = pygame.font.Font(pygame.font.get_default_font(), 60)

    while restart:
        restart = False
        run=True

        net.connect();
        player_nmbr = int(net.get_player_nmbr())
        print("You are player number: ", player_nmbr)
        score = (0,0)
        current_minigame = -1

        if not player_nmbr:#If its first player enter waiting loop
            pygame.display.set_caption('Minigames PVP')
            screen.fill((100, 100, 100))
            text = font.render('Waiting for second player',True, pygame.Color('green'))
            screen.blit(text,(260, 480))
            pygame.display.flip()

            while current_minigame == -1 and run:#LOBBY
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        run = False
                current_minigame = net.current_minigame()
                clock.tick(30)

        pygame.display.set_caption('Minigames PVP Score '+str(score[player_nmbr])+'-'+str(score[(player_nmbr + 1) % 2]))

        while run and all(points < 3 for points in score):#Minigames loop
            current_minigame=net.current_minigame()
            #Show 'next minigame' screen
            screen = pygame.display.set_mode((1280, 960))

            screen.fill((255, 255, 255))
            text = font.render('Next game is ' + game_names[current_minigame-1],True, pygame.Color('black'))
            screen.blit(text,(280, 480))
            pygame.display.flip()

            current_time = pygame.time.get_ticks()
            while run and current_time + 3000 > pygame.time.get_ticks():
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        run = False

            #Start minigame
            game = games[current_minigame - 1](player_nmbr,net)
            try:
                run = game.run()
                score = net.score()
            except SockTimeout:
                print("TIMED OUT !!!")
                run = False
            except SockError as e:
                #Second player left
                print("Enemy Left")
                run = False
                net.close()
            except Exception as e:
                #Some other error
                print(e)
                run = False

            pygame.display.set_caption('Minigames PVP Score '+str(score[player_nmbr])+'-'+str(score[(player_nmbr + 1) % 2]))

        #Game End
        screen = pygame.display.set_mode((1280, 960))
        if net.connected:
            if net.score()[player_nmbr]>=3:
                screen.fill((0, 255, 0))
            else:
                screen.fill((255, 0, 0))

            text = font.render('Press R to start new game',True, pygame.Color('black'))
            screen.blit(text,(260, 480))
        else:
            screen.fill((0, 255, 0))
            text = font.render('Enemy left the game',True, pygame.Color('black'))
            screen.blit(text,(260, 480))
            text = font.render('Press R to start new game',True, pygame.Color('black'))
            screen.blit(text,(260, 540))
            run = True

        pygame.display.flip()
        #End game loop
        while run:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_r:
                        restart = True
                        run = False
            clock.tick(30)
        if net.connected:#We shut connection here and not above to make sure second player gets data before deleting game from server
            net.close()
        if not restart:
            pygame.quit()

if __name__ == "__main__":
    main()


import base64
import jsonrpcclient
from service import registry

if __name__ == "__main__":

    try:
        endpoint = input("Endpoint (localhost:{}): ".format(registry["object_detection_service"]["jsonrpc"]))
        if endpoint == "":
            endpoint = "localhost:{}".format(registry["object_detection_service"]["jsonrpc"])

        rpc_method = "detect"

        model = input("Model (YOLOv3): ")
        if model == "":
            model = "YOLOv3"

        confidence = input("Confidence (0.7): ")
        if confidence == "":
            confidence = "0.7"

        img_path = input("Image (Path or Link): ")

        ret = jsonrpcclient.request(
            "http://{}".format(endpoint),
            rpc_method,
            model=model,
            confidence=confidence,
            img_path=img_path,
        )
        delta_time = ret["result"]["delta_time"]
        img_base64 = ret["result"]["img_base64"]
        print("Delta time: " + str(delta_time))
        # Storing the image into output.jpg
        imgdata = base64.b64decode(img_base64)
        with open("output.jpg", "wb") as f:
            f.write(imgdata)
        print("Done!")

    except Exception as e:
        print(e)


from cpf_field.models import CPFField
from django.db import models
from localflavor.br.models import BRCNPJField, BRPostalCodeField
from phone_field import PhoneField

class Tb_estoque(models.Model):
    id_estoque = models.IntegerField(primary_key=True, verbose_name='Id do estoque')
    id_produto = models.IntegerField(verbose_name='Código do prodúto', null=True)
    ds_n = models.CharField(max_length=45, verbose_name='Nome')
    tamanhoCHOICES = [
        ('PP', 'PP'),
        ('P', 'P'),
        ('M', 'M'),
        ('G', 'G'),
        ('GG', 'GG'),
    ]
    ds_tamanho = models.CharField(max_length=2, verbose_name='Tamanho', null=True, choices= tamanhoCHOICES)
    corCHOICES = [
        ('Branco', 'Branco'),
        ('Preto', 'Preto'),
        ('Verde', 'Verde'),
        ('Rosa', 'Rosa'),
        ('Vermelho', 'Vermelho'),
    ]
    ds_cor = models.CharField(max_length=10, verbose_name='Cor', null=True, choices=corCHOICES)
    vl_preco_custo = models.DecimalField(decimal_places=2, max_digits=15, verbose_name='Custo',null=True)
    vl_preco_venda = models.DecimalField(decimal_places=2, max_digits=15, verbose_name='Preço de venda', null=True)
    dt_entrada = models.DateField(verbose_name='Data de entrada', null=True)

    class Meta:
        ordering = ('ds_n',)
        verbose_name = 'Estoque'
        verbose_name_plural = 'Estoque'

    def __str__(self):
        return self.ds_n

class Tb_cor(models.Model):
    cor = models.CharField(max_length=45)

class Tb_cliente(models.Model):
    nome = models.CharField(max_length=100, verbose_name='Nome')
    cpf = CPFField('cpf')
    cep = BRPostalCodeField(null=True, verbose_name='Cep')
    email = models.EmailField(null=True, verbose_name='Email')
    endereco = models.CharField(max_length=200, verbose_name='Endereço')
    bairro = models.CharField(max_length=50, verbose_name='Bairro')
    uf = models.CharField(max_length=2, verbose_name='Uf')
    dt_nascimento = models.DateField(verbose_name='Data de nascimento')

    class Meta:
        ordering = ('nome',)
        verbose_name = 'Cliente'
        verbose_name_plural = 'Clientes'

    def __str__(self):
        return self.nome

class Tb_usuario(models.Model):
    nome = models.CharField(max_length=100, verbose_name='Nome')
    cpf = CPFField('cpf')
    cep = BRPostalCodeField(null=True, verbose_name='Cep')
    endereco = models.CharField(max_length=200, verbose_name='Endereço')
    email = models.EmailField()
    telefone = PhoneField(blank=True, help_text='Número de contato')
    dt_nascimento = models.DateField(verbose_name='Data de nascimento')

    class Meta:
        ordering = ('nome',)
        verbose_name = 'Usuário'
        verbose_name_plural = 'Usuários'

    def __str__(self):
        return self.nome

class Tb_fornecedor(models.Model):
    nome = models.CharField(max_length=100, verbose_name='Nome')
    cnpj = BRCNPJField(null=True, blank=True)
    cep = BRPostalCodeField(null=True, verbose_name='Cep')
    endereco = models.CharField(max_length=200, verbose_name='Endereço')
    email = models.EmailField()
    telefone = PhoneField(blank=True, help_text='Número de contato')
    codigo = models.IntegerField(verbose_name='Código do prodúto')
    proChoices = [
        ('Blusa', 'Blusa'),
        ('Saia', 'Saia'),
        ('Calça', 'Calça'),
        ('Moletom', 'Moletom'),
        ('Bone', 'Bone'),
    ]
    tipo = models.CharField(max_length=45, verbose_name='Tipo do prodúto', choices=proChoices)

    class Meta:
        ordering = ('nome',)
        verbose_name = 'Fornecedor'
        verbose_name_plural = 'Fornecedores'

    def __str__(self):
        return self.nome

class Cart(models.Model):
    usuario = models.ForeignKey(Tb_usuario, on_delete=models.DO_NOTHING, verbose_name="Usuário")
    cliente = models.ForeignKey(Tb_cliente, on_delete=models.DO_NOTHING,)
    produto = models.ForeignKey(Tb_estoque, on_delete=models.DO_NOTHING, verbose_name="Prodúto")
    tamanhoCHOICES = [
        ('PP', 'PP'),
        ('P', 'P'),
        ('M', 'M'),
        ('G', 'G'),
        ('GG', 'GG'),
    ]
    tamanho = models.CharField(max_length=2, verbose_name='Tamanho', null=True, choices=tamanhoCHOICES)
    corCHOICES = [
        ('Branco', 'Branco'),
        ('Preto', 'Preto'),
        ('Verde', 'Verde'),
        ('Rosa', 'Rosa'),
        ('Vermelho', 'Vermelho'),
    ]
    cor = models.CharField(max_length=10, verbose_name='Cor', null=True, choices=corCHOICES)
    newV = models.DecimalField(decimal_places=2, max_digits=15, verbose_name='Preço da venda', null=True)

    class Meta:
        verbose_name = ('Carrinho')
        verbose_name_plural = 'Carrinho'


import datetime

from django.test import TestCase
from django.utils import timezone

from .models import Experience

class ExperienceMethodTests(TestCase):

    def test_num_years_exact(self):
        """
        Tests num_years() when exactly one year apart between start and
        end date.
        """
        now = timezone.now()
        xp = Experience(
            parent=None,
            name="Test",
            start=now - datetime.timedelta(days=365),
            end=now,
        )
        self.assertEqual(xp.num_years(), 1.0)

    def test_num_years_partial(self):
        """
        Tests num_years() when there is a partial year between start and
        end date.
        """
        now = timezone.now()
        xp = Experience(
            parent=None,
            name="Test",
            start=now - datetime.timedelta(days=73),
            end=now,
        )
        self.assertEqual(xp.num_years(), 0.2)

    def test_num_years_same_date(self):
        """
        Tests num_years() when there is no difference between start and
        end date.
        """
        now = timezone.now()
        xp = Experience(
            parent=None,
            name="Test",
            start=now,
            end=now,
        )
        self.assertEqual(xp.num_years(), 0.0)

    def test_get_children_when_none(self):
        """
        Tests the get_children method when there are no children
        """
        now = timezone.now()
        xp = Experience(
            parent=None,
            name="Test",
            start=now,
            end=now,
        )

        xp.save()

        self.assertEqual(xp.get_children().count(), 0)

    def test_get_children_when_only_child(self):
        """
        Tests the get_children method when there is one child
        """
        now = timezone.now()
        xp = Experience(
            parent=None,
            name="Test",
            start=now,
            end=now,
        )
        child = Experience(
            parent=xp,
            name="Child",
            start=now,
            end=now,
        )

        xp.save();
        child.save();

        children = xp.get_children()

        self.assertEqual(children.count(), 1)
        self.assertEqual(children[0], child)


# Parses Project Scripts, Base Scripts, Definition Files, and CRC Files

# TODO: figure out what is $CRCCHECK is
# may need to add a /crccheck launch option to have this thing only check the crc of a file

import os
import hashlib
import PyQPC_Base as base

class ProjectBlock:
    def __init__(self, key, values=[], conditional=None):
        self.key = key
        self.values = []
        self.values.extend(values)
        self.conditional = conditional
        self.items = []

    def AddItem(self, item):
        self.items.append(item)

class Project:
    def __init__(self, name, path, macros, conditionals):
        self.file_name = name  # the actual file name
        self.name = name  # the project name
        # self.path = path # folder the project script is in (using $PROJECTDIR instead, maybe use this instead?)

        # i might change this to just be a huge list, and have the folder it goes in in the file object
        self.files = []  # dictionary because folders

        self.libraries = []  # maybe change to dependencies?

        # maybe add an "self.other_files" dictionary where the files aren't objects and just the paths?
        # and only use self.files for h and cpp files?

        # if the key is an integer, it's a file
        # if the key is a string, it's a folder

        self.config = {}

        # self.project_scripts = []

        self.crc_list = {}

        self.macros = {"$PROJECTDIR": path, "$PROJECTNAME": name}
        for key, value in macros.items():
            self.macros[key] = value

        self.macros_required = {}

        self.conditionals = {}
        for key, value in conditionals.items():
            self.conditionals[key] = value

    def AddMacro(self, values, required=False):
        key_name = "$" + values[0].upper()

        try:
            value = values[1]
        except:
            value = ''

        if required and value == '':
            if key_name not in self.macros:
                self.macros_required[key_name] = value
        else:
            # remove it from the required list if it's in it?
            if key_name in self.macros_required:
                del self.macros_required[key_name]
            if key_name not in self.macros:
                self.macros[key_name] = value

        self.ReplaceAnyUndefinedMacros()
        self.AddConditional(values)

        return

    def ReplaceAnyUndefinedMacros(self):
        # this could probably be sped up
        # TODO: add scanning of files and certain config settings
        for macro, value in self.macros.items():
            self.macros[macro] = ReplaceMacros(value, self.macros, self.macros_required)

    def AddConditional(self, values):

        if len(values) < 2:
            return

        try:
            self.conditionals["$" + values[0].upper()] = int(values[1])
        except ValueError:
            pass

    def AddFile(self, folder_list, file_list):

        for file_path in file_list:

            # TODO: add a cmd option check for /hidewarnings here
            if self.GetFileObject(file_path):
                if not base.FindCommand("/hidewarnings"):
                    print("WARNING: File already added: \"" + file_path + "\"")
                return

            self.files.append(ProjectFile(file_path, folder_list, self.config))

    def GetAllFileFolderDepthLists(self):

        folder_lists = []
        for file_obj in self.files:
            if file_obj.folder_depth_list not in folder_lists and file_obj.folder_depth_list != []:
                folder_lists.append(file_obj.folder_depth_list)

        return folder_lists

    def GetAllFileFolderPaths(self):

        folder_paths = []
        for file_obj in self.files:
            if file_obj.folder_path not in folder_paths and file_obj.folder_path != '':
                folder_paths.append(file_obj.folder_path)

        return folder_paths

    def GetFileObjectsInFolder(self, folder_list):

        file_obj_list = []
        for file_obj in self.files:
            if file_obj.folder_depth_list == folder_list:
                file_obj_list.append(file_obj)

        return file_obj_list

    def GetFileObject(self, file_path):

        for file_obj in self.files:
            if file_obj.path == file_path:
                return file_obj

        return False

    # TODO: i probably need to add more stuff here for the prefix and ext macros
    # also add a check file option, since sometimes i may use "$DynamicFile" for a lib
    # maybe make a DynamicLib option? idk
    def AddLib(self, lib_path, implib=False):
        # TODO: fix this for if you have multiple libs in the value
        lib_path = lib_path[0]

        # remove this ugly ass hack valve did later
        if not os.sep in lib_path:
            lib_path = self.macros["$LIBPUBLIC"] + os.sep + lib_path

        # wow u dumb
        '''
        try:
            # get rid of the path separators if there are any
            file_name = file
            if os.sep in file_name:
                file_name = file.rsplit( os.sep, 1 )[1]

            # try splitting it to get the file extension, it will throw an exception if doesn't have one
            file_ext_test = file_name.rsplit( ".", 1 )[1]

        except:
        '''

        if implib:
            lib_ext = self.macros["$_STATICLIB_EXT"]
        else:
            lib_ext = self.macros["$_STATICLIB_EXT"]

        if not lib_path.endswith(lib_ext):
            lib_path += lib_ext

        if lib_path not in self.libraries:
            self.libraries.append(lib_path)
        else:
            if not base.FindCommand("/hidewarnings"):
                print("WARNING: Library already added: \"" + lib_path + "\"")

    def RemoveLib(self, file, implib=False):
        # TODO: fix this for if you have multiple libs in the value
        file = file[0]

        # remove this ugly ass hack valve did later
        if not os.sep in file:
            file = self.macros["$LIBPUBLIC"] + os.sep + file

        if implib:
            file += self.macros["$_IMPLIB_EXT"]
        else:
            file += self.macros["$_STATICLIB_EXT"]

        del self.libraries[self.libraries.index(file)]

    def RemoveFile(self, file_list):

        for file_obj in self.files:
            if file_obj.path in file_list:
                del self.files[self.files.index(file_obj)]
                break

class ProjectFile:
    def __init__(self, file_path, folder_list, project_config):
        self.path = file_path
        self.config = {}

        # maybe add a file extension value?

        # folder layout in any editor you want to use
        self.folder_depth_list = []
        self.folder_depth_list.extend(folder_list)  # make sure it's a list even if it's a string
        self.folder_path = os.sep.join(folder_list)

        for config_name in project_config:
            base.CreateNewDictValue(self.config, config_name, "dict")

def AddConfig(project, config):
    if config != '':
        base.CreateNewDictValue(project.config, config, "dict")

def AddConfigGroup(project, config, group_name):
    if config == '':
        for config_name in project.config:
            base.CreateNewDictValue(project.config[config_name], group_name, "dict")
    else:
        base.CreateNewDictValue(project.config[config], group_name, "dict")

def _AddConfigOption(project, config, group_name, option_name, option_value, option_definition):
    if type(option_value) == str:  # and self.config[ config ][ group_name ][ option_name ] != '':
        base.CreateNewDictValue(project.config[config][group_name], option_name, "str")

        if "$BASE" in option_value:
            # add onto what we already have

            base_value = project.config[config][group_name][option_name]

            '''
            option_value_split = option_value.split("$BASE")

            if option_definition.prefer_semicolon_no_comma or option_definition.prefer_semicolon_no_space:
                if not base_value.endswith( ";" ):
                    if not option_value_split[0].endswith( ";" ):
                        if not option_value_split[1].startswith( ";" ):
                            base_value += ";"
            '''

            option_value = option_value.replace("$BASE", base_value)

        project.config[config][group_name][option_name] = option_value
    else:
        project.config[config][group_name].update({option_name: option_value})

def _AddFileConfigOption(project, file_obj, config, group_name, option_name, option_value, option_definition):
    if type(option_value) == str:  # and self.config[ config ][ group_name ][ option_name ] != '':
        base.CreateNewDictValue(file_obj.config[config][group_name], option_name, "str")

        if "$BASE" in option_value:
            # add everything from the project and what we may already have

            # try:
            #     base_value = project.config[config][group_name][option_name]
            # except KeyError:
            #     base_value = ''

            base_value = project.config[config][group_name][option_name]
            option_value = ''.join(option_value.split("$BASE"))

            if option_definition.prefer_semicolon_no_comma or option_definition.prefer_semicolon_no_space:
                if not base_value.endswith(";"):
                    if not option_value.startswith(";"):
                        base_value += ";"

            file_obj.config[config][group_name][option_name] = base_value + option_value

            # file_obj.config[config][group_name][option_name] += value + ''.join( option_value.split("$BASE") )
        else:
            file_obj.config[config][group_name][option_name] = option_value
    else:
        file_obj.config[config][group_name].update({option_name: option_value})

def AddConfigOption(project, config, group_name, option_name, option_value, option_definition, file_obj=None):
    # check if the config name is '', if it is, add it to all configurations
    # this won't add onto an option, this will just replace it
    # so maybe check the type for if we should replace it or not
    if config == '':
        for config_name in project.config:
            if file_obj:
                _AddFileConfigOption(project, file_obj, config_name, group_name, option_name, option_value,
                                     option_definition)
            else:
                _AddConfigOption(project, config_name, group_name, option_name, option_value, option_definition)
    else:
        if file_obj:
            _AddFileConfigOption(project, file_obj, config, group_name, option_name, option_value, option_definition)
        else:
            _AddConfigOption(project, config, group_name, option_name, option_value, option_definition)
    return

def GetConfigOptionValue(project, config, group_name, option_name, option_value, file_obj=None):
    if not option_value or config == '':
        return

    if file_obj:
        try:
            return file_obj.config[config][group_name][option_name]
        except KeyError:
            return None

    else:
        try:
            return project.config[config][group_name][option_name]
        except KeyError:
            return None

class DefinitionsFile:
    def __init__(self, file):
        self.file = file
        self.version = 0
        self.groups = {}

    def SetVersion(self, version):
        self.version = int(version)

    def AddGroup(self, group_name):
        base.CreateNewDictValue(self.groups, group_name, "list")

    def AddOption(self, group_name, option):
        self.groups[group_name].append(option)

class ConfigOption:
    def __init__(self, key):
        self.key = key
        self.type = "ignore"

        # this is a list because the order of these matter, as it uses the top one by default
        self.ordinals = []

        self.output = None  # what the key name will be instead

        # alternative key names
        self.alias = None
        self.legacy = None

        # booleans
        self.append_slash = False  # adds a slash to the end of it?
        self.fix_slashes = False
        self.prefer_semicolon_no_comma = False
        self.prefer_semicolon_no_space = False
        self.invert_output = False

        # idk yet
        self.global_property = False  # allows this key to be used anywhere

    def AddOrdinalOption(self, key, value):
        self.ordinals.append(dict({key: value}))
        # self.ordinals[ key ] = value

    def ConvertOrdinal(self, value):
        if not value:
            return None

        # TODO: change self.ordinals to a dictionary, having it as a list is dumb
        for ordinal in self.ordinals:
            if value[0] in ordinal:
                return ordinal[value[0]]
        else:
            print("ERROR: Unknown Ordinal option: " + value)
            quit()

# maybe add a depth variable here as well? idk
def ReadFile(path, **kwargs):
    with open(path, mode="r", encoding="utf-8") as file:
        file = file.readlines()
    file = base.RemoveCommentsAndFixLines(file)
    file = CleanFile(file)

    return file

# Purpose: to clean up the project script to make parsing it easier
def CleanFile(file):
    cleaned_file = []

    line_num = 0
    while line_num < len(file):

        if file[line_num] == '':
            line_num += 1
            continue

        block = GetFileBlockSplit(file, line_num, False)

        line_num = block[0] - 1
        block = CreateFileBlockObject(block[1])
        cleaned_file.append(block)

        line_num += 1
        continue

    return cleaned_file

def CreateFileBlockObject(block):
    value_list = []
    conditional = None

    value_index = 1
    while len(block[0]) > value_index:

        # don't add any conditional to the value_list
        if "[" in block[0][value_index] or "]" in block[0][value_index]:
            conditional = block[0][value_index][1:-1]  # no brackets on the ends
        else:
            value_list.append(base.RemoveQuotes(block[0][value_index]))
        value_index += 1

    key = ProjectBlock(block[0][0], value_list, conditional)

    if len(block) > 1:

        block_line_num = 1
        while block_line_num < len(block):

            if block[block_line_num] != [] and block[block_line_num][0] != '{' and block[block_line_num][0] != '}':

                sub_block = GetFileBlockSplit(block, block_line_num)

                if isinstance(sub_block[1], list):
                    block_line_num = sub_block[0]  # - 1
                    sub_block = CreateFileBlockObject(sub_block[1])
                    key.AddItem(sub_block)
                    continue

            block_line_num += 1

    return key

# Returns a block into a list with each string split up starting from a line number
def GetFileBlockSplit(file, line_number, has_split_lines=True):
    if has_split_lines:
        line_split = file[line_number]
    else:
        line_split = base.CleanUpSplitLine(file[line_number].split(" "))

    block_depth_num = 0

    block = [line_split]
    if line_split == ['{']:
        block_depth_num = 1

    line_number += 1

    if has_split_lines:
        if file[line_number] != ["{"]:
            return [line_number, block]

    while line_number < len(file):

        if has_split_lines:
            line_split = file[line_number]
        else:
            line_split = base.CleanUpSplitLine(file[line_number].split(" "))

        # the value is split across multiple lines
        if len(block[-1]) > 1 and block[-1][-1] == "\\":
            if line_split != []:
                del block[-1][-1]
                block[-1].extend(line_split)
            line_number += 1
            continue
        else:
            if block_depth_num == 0 and line_split == []:
                break

        if line_split != []:
            if (line_split == ['{']) or (block_depth_num != 0):
                block.append(line_split)

            elif len(block[-1]) > 1:
                if block_depth_num == 0:
                    # this is a single line block like $Macro
                    break

            # this has never called yet, odd
            elif file[line_number] != '' and "{" in file[line_number]:
                # there are items in this block, so add them
                sub_block = GetFileBlockSplit(file, line_number + 1, has_split_lines)
                line_number = sub_block[0]
                block.extend(sub_block[1])
            else:
                break

        if "{" in line_split:
            block_depth_num += 1

        if "}" in line_split:
            block_depth_num -= 1

        line_number += 1

    return [line_number, block]

def ParseBaseFile(base_file, macros, conditionals, unknown_conditionals, project_list, group_list):
    # print( "Parsing Base File: " + "name" )

    definitions_file_path = None

    for project_block in base_file:

        key = project_block.key.casefold()  # compare with ignoring case

        if key == "$CommandLineConditionals".casefold():

            for sub_project_block in project_block.items:
                if sub_project_block.key.upper() in unknown_conditionals:
                    if base.SolveConditional(sub_project_block.conditional, conditionals):
                        conditionals["$" + sub_project_block.key.upper()] = 1
                        del unknown_conditionals[unknown_conditionals.index(sub_project_block.key.upper())]

        elif key == "$Project".casefold():
            base.CreateNewDictValue(project_list, project_block.values[0].casefold(), "list")

            for item in project_block.items:
                if base.SolveConditional(item.conditional, conditionals):
                    item.key = ReplaceMacros(item.key, macros)
                    project_list[project_block.values[0].casefold()].append(item.key)

        elif key == "$Group".casefold():
            # TODO: fix this for multiple groups
            base.CreateNewDictValue(group_list, project_block.values[0], "list")

            for item in project_block.items:
                if base.SolveConditional(item.conditional, conditionals):
                    item.key = ReplaceMacros(item.key, macros)
                    group_list[project_block.values[0].casefold()].append(item.key)

        elif key == "$Definitions".casefold():
            definitions_file_path = ReplaceMacros(project_block.values[0], macros)

        elif project_block.key.casefold() == "$Conditional".casefold():
            # TODO_ERROR: add error checking here if value_str can't be an integer and if no value was given
            conditionals["$" + project_block.values[0].upper()] = int(project_block.values[1])

        elif project_block.key.casefold() == "$Macro".casefold():
            macros["$" + project_block.values[0].upper()] = ReplaceMacros(project_block.values[1], macros)

        # FIX THIS
        elif project_block.key.casefold() == "$MacroRequired".casefold():
            macros["$" + project_block.values[0].upper()] = ReplaceMacros(project_block.values[1], macros)

        elif project_block.key.casefold() == "$Include".casefold():
            # "Ah shit, here we go again."
            path = os.path.normpath(ReplaceMacros(project_block.values[0], macros))

            # maybe add a depth counter like in parsing projects?
            if base.FindCommand("/verbose"):
                print("Reading: " + path)

            include_file = ReadFile(path)
            ParseBaseFile(include_file, macros, conditionals, unknown_conditionals, project_list, group_list)

        else:
            print("Unknown Key: " + project_block.key)

    return definitions_file_path

def ParseProjectFile(project_file, project, definitions, depth=0):
    for project_block in project_file:

        key = project_block.key.casefold()  # compare with ignoring case

        # check if the conditional result is true before checking the key
        if base.SolveConditional(project_block.conditional, project.conditionals):

            # replace any macros HERE, not in each function
            # this better not cause any issues...
            for value in project_block.values:
                index = project_block.values.index(value)
                project_block.values[index] = ReplaceMacros(value, project.macros, project.macros_required)

            if key == "$configuration":
                ParseConfigBlock(project_block, project, definitions, project.conditionals, project.macros,
                                 project.macros_required)

            elif key == "$project":
                ParseProjectBlock(project_block, project, definitions)

            elif key == "$conditional":
                project.AddConditional(project_block.values)

            elif key == "$macro":
                project.AddMacro(project_block.values)

            elif key == "$macrorequired":
                project.AddMacro(project_block.values, True)

            elif key == "$macrorequiredallowempty":
                project.AddMacro(project_block.values, True)

            elif key == "$include":
                # Ah shit, here we go again.
                # path = ReplaceMacros( project_block.values[0], project.macros, project.macros_required )
                path = project_block.values[0]

                if base.FindCommand("/verbose"):
                    depth += 1
                    space = []
                    while len(space) < depth:
                        space.append("    ")

                    print(''.join(space) + "Reading: " + path)

                # full_path = os.path.join( project.macros[ "$PROJECTDIR" ], path )
                full_path = os.path.normpath(project.macros["$PROJECTDIR"] + os.sep + path)

                project.crc_list[path] = MakeCRC(full_path)

                include_file = ReadFile(full_path)

                if base.FindCommand("/verbose"):
                    print(''.join(space) + "Parsing: " + path)

                ParseProjectFile(include_file, project, definitions, depth)

                if base.FindCommand("/verbose"):
                    print(''.join(space) + "Parsed: " + path)
                    depth -= 1

            elif key == "$IgnoreRedundancyWarning".casefold() or key == "$linux" or key == "$LoadAddressMacro".casefold() or key == "$LoadAddressMacroAuto".casefold():
                pass

            else:
                print("ERROR: Unknown key found: " + key)

    return  # project

def ParseProjectBlock(project_block, project, definitions):
    # project.AddFileFolder( folder_list )
    # project.AddFile( folder_list, file )
    # project.GetFileObject( file )
    # project.AddLib( file, implib = False )
    # project.RemoveLib( file, implib = False )
    # project.RemoveFile( file )

    if base.SolveConditional(project_block.conditional, project.conditionals):

        # if project_block.values != []:
        if project_block.values:
            project.name = project_block.values[0]

        # now go through each item
        for block in project_block.items:
            if base.SolveConditional(block.conditional, project.conditionals):

                for value in block.values:
                    index = block.values.index(value)
                    block.values[index] = ReplaceMacros(value, project.macros, project.macros_required)

                if block.key.casefold() == "$folder":
                    ParseFolder(block, project, definitions)

                elif "$file" in block.key.casefold() or "$dynamicfile" in block.key.casefold() \
                    or "$lib" in block.key.casefold() or "$implib" in block.key.casefold():
                    ParseFile(block, project, definitions)

                else:
                    print("Unknown Key: " + block.key)

def ParseFolder(folder_block, project, definitions, folder_list=[]):
    # project.AddFileFolder( folder_list )
    # project.AddFile( folder_list, file )
    # project.GetFileObject( file )
    # project.AddLib( file, implib = False )
    # project.RemoveLib( file, implib = False )
    # project.RemoveFile( file )

    folder_list.append(folder_block.values[0])
    # project.AddFileFolder( folder_list )

    for block in folder_block.items:
        if base.SolveConditional(block.conditional, project.conditionals):

            for value in block.values:
                index = block.values.index(value)
                block.values[index] = ReplaceMacros(value, project.macros, project.macros_required)

            if block.key.casefold() == "$folder":
                ParseFolder(block, project, definitions, folder_list)

            elif "$file" in block.key.casefold() or "$dynamicfile" in block.key.casefold() \
                or "$lib" in block.key.casefold() or "$implib" in block.key.casefold():
                ParseFile(block, project, definitions, folder_list)

            elif "$shaders" in block.key.casefold():
                pass

            else:
                print("Unknown Key: " + block.key)

    # now "leave" the last folder
    del folder_list[-1]

def ParseFile(file_block, project, definitions, folder_list=[]):
    # project.AddFile( folder_list, file )
    # project.GetFileObject( file )
    # project.AddLib( file, implib = False )
    # project.RemoveLib( file, implib = False )
    # project.RemoveFile( file )

    # for value in file_block.values:
    # index = file_block.values.index( value )
    # file_block.values[ index ] = ReplaceMacros( value, project.macros, project.macros_required )

    # ew
    if folder_list != [] and folder_list[-1] == "Link Libraries":
        if not "lib" in file_block.key.casefold():
            file_block.key = "$Lib"

    if file_block.key.casefold() == "$file":
        project.AddFile(folder_list, file_block.values)

        if file_block.items != []:
            for file_path in file_block.values:
                file_object = project.GetFileObject(file_path)
                ParseConfigBlock(file_block.items[0], project, definitions, project.conditionals, project.macros,
                                 project.macros_required, file_object)

    elif file_block.key.casefold() == "$dynamicfile":
        project.AddFile(folder_list, file_block.values)
        # these don't have config blocks, right? idk
        # not hard to add though, just copy the 3 lines above

    elif file_block.key.casefold() == "$lib":
        project.AddLib(file_block.values)

    elif file_block.key.casefold() == "$implib":
        project.AddLib(file_block.values, True)

    # ----------------------------------------------------------
    # Removing Files now
    elif file_block.key.casefold() == "-$file":
        project.RemoveFile(file_block.values)

    elif file_block.key.casefold() == "-$lib":
        project.RemoveLib(file_block.values)

    elif file_block.key.casefold() == "-$implib":
        project.RemoveLib(file_block.values, True)

    else:
        print("unknown key: " + file_block.key)

# dammit, i accidentally made this so you can only have an option in a group
# and can't have a group in a group, not really sure if i should bother fixing it right now though
# TODO: split this up into ParseConfigGroup() and ParseConfigOption(), so you can parse it recursively
def ParseConfigBlock(project_block, project, definitions, conditionals, macros, macros_required, file_obj=None):
    # TODO: do something with the definitions here, maybe check what it is? idfk
    # or maybe add that definition option into the project config?

    if project_block.values == []:
        config_name = ""  # add it to all configs
        # platform = "" # all platforms as well
    else:
        config_name = project_block.values[0]
        # if len(values) > 1:
        #   platform = project_block.values[1]
        # else:
        #   platform = ""  # add the options to all platforms in this config

    if base.SolveConditional(project_block.conditional, conditionals):

        if file_obj:
            AddConfig(file_obj, config_name)
        else:
            AddConfig(project, config_name)

        for group_block in project_block.items:
            if base.SolveConditional(group_block.conditional, conditionals):
                if group_block.key in definitions.groups:

                    if file_obj:
                        AddConfigGroup(file_obj, config_name, group_block.key)
                    else:
                        AddConfigGroup(project, config_name, group_block.key)

                    for option_block in group_block.items:
                        if base.SolveConditional(option_block.conditional, conditionals):

                            # maybe move this to ParseConfigOption()?
                            # that way you don't have to use an option in a group? idk
                            compare_name = option_block.key.casefold()
                            for option_definition in definitions.groups[group_block.key]:
                                # PAIN
                                if compare_name == option_definition.key.casefold() or \
                                    (option_definition.alias and compare_name == option_definition.alias.casefold()) or \
                                    (option_definition.legacy and compare_name == option_definition.legacy.casefold()):

                                    # floods the console with $PrecompiledHeaderFile
                                    if base.FindCommand("/showlegacyoptions"):
                                        if option_definition.legacy != None and compare_name == option_definition.legacy.casefold():
                                            print("Legacy option: " + option_block.key)

                                    if option_definition.output:
                                        name = option_definition.output
                                    else:
                                        name = option_definition.key
                                    value = option_block.values

                                    if value == []:
                                        break

                                    if "$" in name:
                                        name = name.split("$", 1)[1]

                                    if option_definition.type == "ignore":
                                        break
                                    elif option_definition.type == "string":
                                        value = ReplaceMacros(''.join(option_block.values), macros, macros_required)

                                    elif option_definition.type == "ordinals":
                                        value = option_definition.ConvertOrdinal(value)

                                    elif option_definition.type == "bool":
                                        if value[0].lower().startswith("no") or value[0].lower().startswith("false"):
                                            value = "False"
                                        elif value[0].lower().startswith("yes") or value[0].lower().startswith("true"):
                                            value = "True"
                                        else:
                                            print("unknown bool option: " + value)

                                        if option_definition.invert_output:
                                            value = not value

                                    elif option_definition.type == "integer":
                                        print("integer is not setup yet as it is never used")

                                    else:
                                        print("unknown key type: " + option_definition.key)

                                    # should i use the replace function instead?
                                    if option_definition.prefer_semicolon_no_comma:
                                        value = value.replace(",", ";")

                                    if option_definition.prefer_semicolon_no_space:
                                        value = value.replace(" ", ";")

                                    if option_definition.append_slash:
                                        if not value.endswith(os.sep):
                                            value = value + os.sep

                                    if option_definition.fix_slashes:
                                        if value != '':
                                            value = os.path.normpath(value)

                                    if value:
                                        AddConfigOption(project, config_name, group_block.key, name, value,
                                                        option_definition, file_obj)
                                    break

                            else:
                                print("Unknown option: " + option_block.key)
                else:
                    print("Unknown group: " + group_block.key)

# maybe make a configuration options class?
# and all the items be keys or groups
def ParseDefFile(def_file):
    definitions = DefinitionsFile(def_file.key)

    for def_group in def_file.items:

        if def_group.key == "Version":
            definitions.SetVersion(def_group.values[0])
            continue

        # maybe add an option in the def file for changing it?
        # like adding the output name next to the group name?
        # example: "$Compiler"  "ClCompile" {}
        definitions.AddGroup(def_group.key)

        for def_key in def_group.items:
            config_option = ConfigOption(def_key.key)

            for option in def_key.items:

                if option.key == "type":
                    config_option.type = option.values[0]

                elif option.key == "ordinals":
                    config_option.type = "ordinals"
                    for ordinal_option in option.items:
                        config_option.AddOrdinalOption(ordinal_option.key, ordinal_option.values[0])

                elif option.key == "output":
                    config_option.output = option.values[0]

                # idfk
                elif option.key == "globalproperty":
                    config_option.global_property = option.values[0]

                # add a slash to the end of the value
                elif option.key == "AppendSlash":
                    config_option.append_slash = option.values[0]

                # fix the path seperators if needed
                elif option.key == "fixslashes":
                    config_option.fix_slashes = option.values[0]

                # change to "ReplaceCommaWithSemicolon"?
                elif option.key == "PreferSemicolonNoComma":
                    config_option.prefer_semicolon_no_comma = option.values[0]

                # change to "ReplaceSpaceWithSemicolon"?
                elif option.key == "PreferSemicolonNoSpace":
                    config_option.prefer_semicolon_no_space = option.values[0]

                # changes bools to the opposite value
                elif option.key == "invertoutput":
                    config_option.invert_output = option.values[0]

                # in the def file, but the key is different so this is never used
                elif option.key == "alias":
                    config_option.alias = option.values[0]

                # option can also be called this
                elif option.key == "legacy":
                    config_option.legacy = option.values[0]

            # and now add that key to the Definitions Object
            definitions.AddOption(def_group.key, config_option)

    return definitions

def ReplaceMacros(string, macros, macros_required={}):
    if "$" in string:
        # go through all the known macros and check if each one is in the value
        for macro, macro_value in macros.items():
            if macro in string:
                string_split = string.split(macro)
                # should use os path join or something if it has os.sep in the macro and/or string
                string = macro_value.join(string_split)

        for macro, macro_value in macros_required.items():
            if macro in string:
                string_split = string.split(macro)
                # should use os path join or something if it has os.sep in the macro and/or string
                string = macro_value.join(string_split)

    return string

def WriteDependencyList():
    pass

def ParseProject(project_script_path, base_macros, base_conds, definitions):
    project_filename = project_script_path.rsplit(os.sep, 1)[1]
    project_name = project_filename.rsplit(".", 1)[0]

    project_dir = os.path.join(base_macros["$ROOTDIR"], project_script_path.rsplit(os.sep, 1)[0])

    project_path = os.path.join(project_dir, project_filename)

    project = Project(project_name, project_dir, base_macros, base_conds)

    project.crc_list[project_filename] = MakeCRC(project_path)

    if base.FindCommand("/verbose"):
        print("Reading: " + project_filename)

    project_file = ReadFile(project_path)

    if base.FindCommand("/verbose"):
        print("Parsing: " + project_filename)
    else:
        print("Parsing: " + project.name)

    ParseProjectFile(project_file, project, definitions, 0)

    # dependency_list = []
    # dependency_list.extend( project.libraries )
    # will add more later

    # WriteDependencyList( dependency_list ) # change this to dependencies

    return project

def CRCCheck(root_dir, project_path):
    project_crc_path = os.path.join(root_dir, project_path + "_crc")

    if os.sep in project_path:
        project_path = project_path.rsplit(os.sep, 1)[0]

    project_dir = os.path.join(root_dir, project_path) + os.sep

    # open the crc file if it exists,
    # run MakeCRC on every file there
    # and check if it matches what MakeCRC returned
    if os.path.isfile(project_crc_path):
        crc_file = ReadFile(project_crc_path)  # i could use this for it as well lmao

        for crc_line in crc_file:
            project_crc = crc_line.key
            project_file_path = os.path.join(project_dir, crc_line.values[0])

            if project_crc != MakeCRC(project_file_path):
                print("Invalid: " + crc_line.values[0] + "_crc")
                return True

        return False
    else:
        print("CRC File does not exist")
        return True

# Source: https://bitbucket.org/prologic/tools/src/tip/md5sum
def MakeCRC(filename):
    hash = hashlib.md5()
    with open(filename, "rb") as f:
        for chunk in iter(lambda: f.read(128 * hash.block_size), b""):
            hash.update(chunk)
    return hash.hexdigest()

def MakeCRCFile(project_path, crc_list):
    project_path += "_crc"
    with open(project_path, mode="w", encoding="utf-8") as crc_file:
        for project_script_path, crc in crc_list.items():
            crc_file.write(crc + " " + project_script_path + "\n")

    return


# Write a program that prints the numbers 1 - 100
# For multiples of 3, also print "Fizz"
# For multiples of 5, also print "Buzz"
# For multiples of both 3 and 5, print "FizzBuzz"

def main():
    for i in range (1,101):
        if i % 3 == 0 and i % 5 == 0:
            print("FizzBuzz")
        elif i % 3 == 0 and i % 5 != 0:
            print("Fizz")
        elif i % 5 == 0 and i % 3 != 0:
            print("Buzz")
        else:
            print(str(i))
main()


from sense_hat import SenseHat
from time import sleep

sense = SenseHat()

def refresh(x, y):
    sense.clear()
    sense.set_pixel(x, y, 255, 255, 255)

while True:
    raw = sense.get_orientation_degrees()
    x_axis = raw['roll']
    print(raw['roll'])

    if x_axis > 270 and x_axis <= 360:
        refresh(4, int((x_axis / 22.5) % 4))
    elif x_axis > 0 and x_axis <= 90:
        refresh(4, int((x_axis / 22.5) % 4) + 4)