from splinter.browser import Browser

def main():
    b = Browser('chrome')
    b.driver.set_window_size(1600, 1000)
    url = 'https://www.baidu.com/'
    b.visit(url)
    if b.is_text_present(u'关于百度'):
        print("yes, found it!")
    else:
        print("no, did not found it!")
    b.fill('wd', 'splink')
    third_found = b.find_by_id(u'su').click()

if __name__ == '__main__':
    main()


import allure

# from seledka.libs.screenshot import ScreenShots

class BaseSoftAssert(object):
    def check_assert_errors(self):
        if self.assert_errors != '\n':
            raise AssertionError(self.assert_errors)

    def add_failed_info(self, msg, error):
        with allure.step(f'[SoftAssertion]: {msg}'):
            # if hasattr(self, 'driver'):
            #     allure.attach(
            #         ScreenShots(self.driver).take_screenshot().content,
            #         name=self.driver.current_url,
            #         attachment_type=allure.attachment_type.PNG
            #     )
            allure.attach(
                error,
                name='В чём ошибка',
                attachment_type=allure.attachment_type.JSON
            )
            if msg:
                error += f"\t{'Примечание: ' + msg}\n"
            self.assert_errors += (error + self.base_msg())

    def soft_assert_equal(self, current, excepted, message=None):
        if current != excepted:
            error = (
                f"*-------- Soft Assertion (Не совпадают значения) --------*\n"
                f"\tТекущее: '{current}'\n"
                f"\tОжидаемое: '{excepted}'\n"
            )
            self.add_failed_info(message, error)

    def soft_assert_not_equal(self, current, excepted, message=None):
        if current == excepted:
            error = (
                f"*-------- Soft Assertion (Совпадают значения) --------*\n"
                f"\tТекущее: '{current}'\n"
                f"\tОжидаемое: '{excepted}'\n"
            )
            self.add_failed_info(message, error)

    def soft_assert_in(self, member, container, message=None):
        """ Проверка что member находится в container(Частичное вхождение) """
        if member not in container:
            error = (
                f"*------- Soft Assertion (Нет частичного вхождения) ------*\n"
                f"\t'{member}' отсутствует в '{container}'\n"
            )
            self.add_failed_info(message, error)

class WebSoftAssert(BaseSoftAssert):

    def base_msg(self):
        return (
            f"\turl: {self.driver.current_url}\n"
            f"\tScreenshot - ..skip..\n\n"
            # ScreenShots(self.driver).take_screenshot().url
        )

    def soft_assert_page_title(
            self, expected_title, msg="Не правильный заголовок странички"
    ):
        """ Проверка названия заголовка страницы """
        self.soft_assert_equal(self.driver.title, expected_title, msg)

    def soft_assert_current_url(
            self, expected_url, msg="Не правильный текущий url"
    ):
        """ Проверка url текущей страницы """
        self.soft_assert_equal(self.driver.current_url, expected_url, msg)

    def soft_assert_current_url_contains(
            self, url_mask, msg='Не правильный шаблон в url'
    ):
        """ Проверка частичного наименования url текущей страницы """
        self.soft_assert_in(url_mask, self.driver.current_url, msg)

class RequestSoftAssert(BaseSoftAssert):

    @property
    def url(self):
        try:
            return self.response.url
        except Exception:
            return ''

    def base_msg(self):
        return f"\turl: {self.url}\n\n"


import argparse
import requests
from bs4 import BeautifulSoup
import json

parser = argparse.ArgumentParser()
parser.add_argument("file_name", help="name of created json file")
args = parser.parse_args()

name = args.file_name+".json"
req = requests.get('https://en.wikipedia.org/wiki/Index_of_feminism_articles')
status = req.status_code

print("Status code = ", status)
print("Information will be saved into: ", name)

soup = BeautifulSoup(req.text,'html.parser')
articles = soup.find('div', {'class': 'mw-parser-output'})

feminism_articles = []

for article in articles.find_all('a'):
    try:
        reference = article['href']
        title = article['title']
        if (title,reference) not in feminism_articles:
            feminism_articles.append((title,reference))
    except:
        pass

with open(name, 'w') as f:
    json.dump(feminism_articles, f)


from pathlib import Path, PurePath
import math
import re
import time
import uuid
from typing import Any, Tuple, List

from librespot.metadata import TrackId
import ffmpy

from zotify.const import TRACKS, ALBUM, GENRES, NAME, ITEMS, DISC_NUMBER, TRACK_NUMBER, IS_PLAYABLE, ARTISTS, IMAGES, URL, \
    RELEASE_DATE, ID, TRACKS_URL, FOLLOWED_ARTISTS_URL, SAVED_TRACKS_URL, TRACK_STATS_URL, CODEC_MAP, EXT_MAP, DURATION_MS, \
    HREF, ARTISTS, WIDTH
from zotify.termoutput import Printer, PrintChannel
from zotify.utils import fix_filename, set_audio_tags, set_music_thumbnail, create_download_directory, \
    get_directory_song_ids, add_to_directory_song_ids, get_previously_downloaded, add_to_archive, fmt_seconds
from zotify.zotify import Zotify
import traceback
from zotify.loader import Loader

def get_saved_tracks() -> list:
    """ Returns user's saved tracks """
    songs = []
    offset = 0
    limit = 50

    while True:
        resp = Zotify.invoke_url_with_params(
            SAVED_TRACKS_URL, limit=limit, offset=offset)
        offset += limit
        songs.extend(resp[ITEMS])
        if len(resp[ITEMS]) < limit:
            break

    return songs

def get_followed_artists() -> list:
    """ Returns user's followed artists """
    artists = []
    resp = Zotify.invoke_url(FOLLOWED_ARTISTS_URL)[1]
    for artist in resp[ARTISTS][ITEMS]:
        artists.append(artist[ID])

    return artists

def get_song_info(song_id) -> Tuple[List[str], List[Any], str, str, Any, Any, Any, Any, Any, Any, int]:
    """ Retrieves metadata for downloaded songs """
    with Loader(PrintChannel.PROGRESS_INFO, "Fetching track information..."):
        (raw, info) = Zotify.invoke_url(f'{TRACKS_URL}?ids={song_id}&market=from_token')

    if not TRACKS in info:
        raise ValueError(f'Invalid response from TRACKS_URL:\n{raw}')

    try:
        artists = []
        for data in info[TRACKS][0][ARTISTS]:
            artists.append(data[NAME])

        album_name = info[TRACKS][0][ALBUM][NAME]
        name = info[TRACKS][0][NAME]
        release_year = info[TRACKS][0][ALBUM][RELEASE_DATE].split('-')[0]
        disc_number = info[TRACKS][0][DISC_NUMBER]
        track_number = info[TRACKS][0][TRACK_NUMBER]
        scraped_song_id = info[TRACKS][0][ID]
        is_playable = info[TRACKS][0][IS_PLAYABLE]
        duration_ms = info[TRACKS][0][DURATION_MS]

        image = info[TRACKS][0][ALBUM][IMAGES][0]
        for i in info[TRACKS][0][ALBUM][IMAGES]:
            if i[WIDTH] > image[WIDTH]:
                image = i
        image_url = image[URL]

        return artists, info[TRACKS][0][ARTISTS], album_name, name, image_url, release_year, disc_number, track_number, scraped_song_id, is_playable, duration_ms
    except Exception as e:
        raise ValueError(f'Failed to parse TRACKS_URL response: {str(e)}\n{raw}')

def get_song_genres(rawartists: List[str], track_name: str) -> List[str]:
    if Zotify.CONFIG.get_save_genres():
        try:
            genres = []
            for data in rawartists:
                # query artist genres via href, which will be the api url
                with Loader(PrintChannel.PROGRESS_INFO, "Fetching artist information..."):
                    (raw, artistInfo) = Zotify.invoke_url(f'{data[HREF]}')
                if Zotify.CONFIG.get_all_genres() and len(artistInfo[GENRES]) > 0:
                    for genre in artistInfo[GENRES]:
                        genres.append(genre)
                elif len(artistInfo[GENRES]) > 0:
                    genres.append(artistInfo[GENRES][0])

            if len(genres) == 0:
                Printer.print(PrintChannel.WARNINGS, '###    No Genres found for song ' + track_name)
                genres.append('')

            return genres
        except Exception as e:
            raise ValueError(f'Failed to parse GENRES response: {str(e)}\n{raw}')
    else:
        return ['']

def get_song_lyrics(song_id: str, file_save: str) -> None:
    raw, lyrics = Zotify.invoke_url(f'https://spclient.wg.spotify.com/color-lyrics/v2/track/{song_id}')

    if lyrics:
        try:
            formatted_lyrics = lyrics['lyrics']['lines']
        except KeyError:
            raise ValueError(f'Failed to fetch lyrics: {song_id}')
        if(lyrics['lyrics']['syncType'] == "UNSYNCED"):
            with open(file_save, 'w+', encoding='utf-8') as file:
                for line in formatted_lyrics:
                    file.writelines(line['words'] + '\n')
            return
        elif(lyrics['lyrics']['syncType'] == "LINE_SYNCED"):
            with open(file_save, 'w+', encoding='utf-8') as file:
                for line in formatted_lyrics:
                    timestamp = int(line['startTimeMs'])
                    ts_minutes = str(math.floor(timestamp / 60000)).zfill(2)
                    ts_seconds = str(math.floor((timestamp % 60000) / 1000)).zfill(2)
                    ts_millis = str(math.floor(timestamp % 1000))[:2].zfill(2)
                    file.writelines(f'[{ts_minutes}:{ts_seconds}.{ts_millis}]' + line['words'] + '\n')
            return
    raise ValueError(f'Failed to fetch lyrics: {song_id}')

def get_song_duration(song_id: str) -> float:
    """ Retrieves duration of song in second as is on spotify """

    (raw, resp) = Zotify.invoke_url(f'{TRACK_STATS_URL}{song_id}')

    # get duration in miliseconds
    ms_duration = resp['duration_ms']
    # convert to seconds
    duration = float(ms_duration)/1000

    return duration

def download_track(mode: str, track_id: str, extra_keys=None, disable_progressbar=False) -> None:
    """ Downloads raw song audio from Spotify """

    if extra_keys is None:
        extra_keys = {}

    prepare_download_loader = Loader(PrintChannel.PROGRESS_INFO, "Preparing download...")
    prepare_download_loader.start()

    try:
        output_template = Zotify.CONFIG.get_output(mode)

        (artists, raw_artists, album_name, name, image_url, release_year, disc_number,
         track_number, scraped_song_id, is_playable, duration_ms) = get_song_info(track_id)

        song_name = fix_filename(artists[0]) + ' - ' + fix_filename(name)

        for k in extra_keys:
            output_template = output_template.replace("{"+k+"}", fix_filename(extra_keys[k]))

        ext = EXT_MAP.get(Zotify.CONFIG.get_download_format().lower())

        output_template = output_template.replace("{artist}", fix_filename(artists[0]))
        output_template = output_template.replace("{album}", fix_filename(album_name))
        output_template = output_template.replace("{song_name}", fix_filename(name))
        output_template = output_template.replace("{release_year}", fix_filename(release_year))
        output_template = output_template.replace("{disc_number}", fix_filename(disc_number))
        output_template = output_template.replace("{track_number}", fix_filename(track_number))
        output_template = output_template.replace("{id}", fix_filename(scraped_song_id))
        output_template = output_template.replace("{track_id}", fix_filename(track_id))
        output_template = output_template.replace("{ext}", ext)

        filename = PurePath(Zotify.CONFIG.get_root_path()).joinpath(output_template)
        filedir = PurePath(filename).parent

        filename_temp = filename
        if Zotify.CONFIG.get_temp_download_dir() != '':
            filename_temp = PurePath(Zotify.CONFIG.get_temp_download_dir()).joinpath(f'zotify_{str(uuid.uuid4())}_{track_id}.{ext}')

        check_name = Path(filename).is_file() and Path(filename).stat().st_size
        check_id = scraped_song_id in get_directory_song_ids(filedir)
        check_all_time = scraped_song_id in get_previously_downloaded()

        # a song with the same name is installed
        if not check_id and check_name:
            c = len([file for file in Path(filedir).iterdir() if re.search(f'^{filename}_', str(file))]) + 1

            fname = PurePath(PurePath(filename).name).parent
            ext = PurePath(PurePath(filename).name).suffix

            filename = PurePath(filedir).joinpath(f'{fname}_{c}{ext}')

    except Exception as e:
        Printer.print(PrintChannel.ERRORS, '###   SKIPPING SONG - FAILED TO QUERY METADATA   ###')
        Printer.print(PrintChannel.ERRORS, 'Track_ID: ' + str(track_id))
        for k in extra_keys:
            Printer.print(PrintChannel.ERRORS, k + ': ' + str(extra_keys[k]))
        Printer.print(PrintChannel.ERRORS, "\n")
        Printer.print(PrintChannel.ERRORS, str(e) + "\n")
        Printer.print(PrintChannel.ERRORS, "".join(traceback.TracebackException.from_exception(e).format()) + "\n")

    else:
        try:
            if not is_playable:
                prepare_download_loader.stop()
                Printer.print(PrintChannel.SKIPS, '\n###   SKIPPING: ' + song_name + ' (SONG IS UNAVAILABLE)   ###' + "\n")
            else:
                if check_id and check_name and Zotify.CONFIG.get_skip_existing():
                    prepare_download_loader.stop()
                    Printer.print(PrintChannel.SKIPS, '\n###   SKIPPING: ' + song_name + ' (SONG ALREADY EXISTS)   ###' + "\n")

                elif check_all_time and Zotify.CONFIG.get_skip_previously_downloaded():
                    prepare_download_loader.stop()
                    Printer.print(PrintChannel.SKIPS, '\n###   SKIPPING: ' + song_name + ' (SONG ALREADY DOWNLOADED ONCE)   ###' + "\n")

                else:
                    if track_id != scraped_song_id:
                        track_id = scraped_song_id
                    track = TrackId.from_base62(track_id)
                    stream = Zotify.get_content_stream(track, Zotify.DOWNLOAD_QUALITY)
                    create_download_directory(filedir)
                    total_size = stream.input_stream.size

                    prepare_download_loader.stop()

                    time_start = time.time()
                    downloaded = 0
                    with open(filename_temp, 'wb') as file, Printer.progress(
                            desc=song_name,
                            total=total_size,
                            unit='B',
                            unit_scale=True,
                            unit_divisor=1024,
                            disable=disable_progressbar
                    ) as p_bar:
                        b = 0
                        while b < 5:
                        #for _ in range(int(total_size / Zotify.CONFIG.get_chunk_size()) + 2):
                            data = stream.input_stream.stream().read(Zotify.CONFIG.get_chunk_size())
                            p_bar.update(file.write(data))
                            downloaded += len(data)
                            b += 1 if data == b'' else 0
                            if Zotify.CONFIG.get_download_real_time():
                                delta_real = time.time() - time_start
                                delta_want = (downloaded / total_size) * (duration_ms/1000)
                                if delta_want > delta_real:
                                    time.sleep(delta_want - delta_real)

                    time_downloaded = time.time()

                    genres = get_song_genres(raw_artists, name)

                    if(Zotify.CONFIG.get_download_lyrics()):
                        try:
                            get_song_lyrics(track_id, PurePath(str(filename)[:-3] + "lrc"))
                        except ValueError:
                            Printer.print(PrintChannel.SKIPS, f"###   Skipping lyrics for {song_name}: lyrics not available   ###")
                    convert_audio_format(filename_temp)
                    try:
                        set_audio_tags(filename_temp, artists, genres, name, album_name, release_year, disc_number, track_number)
                        set_music_thumbnail(filename_temp, image_url)
                    except Exception:
                        Printer.print(PrintChannel.ERRORS, "Unable to write metadata, ensure ffmpeg is installed and added to your PATH.")

                    if filename_temp != filename:
                        Path(filename_temp).rename(filename)

                    time_finished = time.time()

                    Printer.print(PrintChannel.DOWNLOADS, f'###   Downloaded "{song_name}" to "{Path(filename).relative_to(Zotify.CONFIG.get_root_path())}" in {fmt_seconds(time_downloaded - time_start)} (plus {fmt_seconds(time_finished - time_downloaded)} converting)   ###' + "\n")

                    # add song id to archive file
                    if Zotify.CONFIG.get_skip_previously_downloaded():
                        add_to_archive(scraped_song_id, PurePath(filename).name, artists[0], name)
                    # add song id to download directory's .song_ids file
                    if not check_id:
                        add_to_directory_song_ids(filedir, scraped_song_id, PurePath(filename).name, artists[0], name)

                    if not Zotify.CONFIG.get_bulk_wait_time():
                        time.sleep(Zotify.CONFIG.get_bulk_wait_time())
        except Exception as e:
            Printer.print(PrintChannel.ERRORS, '###   SKIPPING: ' + song_name + ' (GENERAL DOWNLOAD ERROR)   ###')
            Printer.print(PrintChannel.ERRORS, 'Track_ID: ' + str(track_id))
            for k in extra_keys:
                Printer.print(PrintChannel.ERRORS, k + ': ' + str(extra_keys[k]))
            Printer.print(PrintChannel.ERRORS, "\n")
            Printer.print(PrintChannel.ERRORS, str(e) + "\n")
            Printer.print(PrintChannel.ERRORS, "".join(traceback.TracebackException.from_exception(e).format()) + "\n")
            if Path(filename_temp).exists():
                Path(filename_temp).unlink()

    prepare_download_loader.stop()

def convert_audio_format(filename) -> None:
    """ Converts raw audio into playable file """
    temp_filename = f'{PurePath(filename).parent}.tmp'
    Path(filename).replace(temp_filename)

    download_format = Zotify.CONFIG.get_download_format().lower()
    file_codec = CODEC_MAP.get(download_format, 'copy')
    if file_codec != 'copy':
        bitrate = Zotify.CONFIG.get_transcode_bitrate()
        bitrates = {
            'auto': '320k' if Zotify.check_premium() else '160k',
            'normal': '96k',
            'high': '160k',
            'very_high': '320k'
        }
        bitrate = bitrates[Zotify.CONFIG.get_download_quality()]
    else:
        bitrate = None

    output_params = ['-c:a', file_codec]
    if bitrate:
        output_params += ['-b:a', bitrate]

    try:
        ff_m = ffmpy.FFmpeg(
            global_options=['-y', '-hide_banner', '-loglevel error'],
            inputs={temp_filename: None},
            outputs={filename: output_params}
        )
        with Loader(PrintChannel.PROGRESS_INFO, "Converting file..."):
            ff_m.run()

        if Path(temp_filename).exists():
            Path(temp_filename).unlink()

    except ffmpy.FFExecutableNotFoundError:
        Printer.print(PrintChannel.WARNINGS, f'###   SKIPPING {file_codec.upper()} CONVERSION - FFMPEG NOT FOUND   ###')


'''

221. maximum square

given a 2D matrix, return the square with only 1
    Example:

    Input:

    1 0 1 0 0
    1 0 1 1 1
    1 1 1 1 1
    1 0 0 1 0

    Output: 4

we go for dynamic programming, break the problem
into smaller problems and then solve it

Easy java code

public class Solution {
    public int maximalSquare(char[][] matrix) {
        int rows = matrix.length, cols = rows > 0 ? matrix[0].length : 0;
        int[][] dp = new int[rows + 1][cols + 1];
        int maxsqlen = 0;
        for (int i = 1; i <= rows; i++) {
            for (int j = 1; j <= cols; j++) {
                if (matrix[i-1][j-1] == '1'){
                    dp[i][j] = Math.min(Math.min(dp[i][j - 1], dp[i - 1][j]), dp[i - 1][j - 1]) + 1;
                    maxsqlen = Math.max(maxsqlen, dp[i][j]);
                }
            }
        }
        return maxsqlen * maxsqlen;
    }
'''

# edge cases missing here
class Solution(object):
    def maximalSquare(self, matrix):
        """
        :type matrix: List[List[str]]
        :rtype: int
        """
        grid = []
        f=1
        for i in matrix:
            a=[0]
            if f == 1:
                for k in i:
                    a.append(0)
                grid.append(a)
                f=0
                continue
            for j in i:
                a.append(int(j))
            grid.append(a)

        print(grid)
        ma = 0
        for i in range(1,len(matrix)):
            for j in range(1,len(matrix)):
                if matrix[i][j]=='1':
                    grid[i][j] = min(grid[i-1][j-1], min(grid[i-1][j], grid[i][j-1]))+1
                    ma = max(grid[i][j], ma)

        print(grid)
        return ma*ma

'''
some changes needed here

'''


# Homework 2 program to determine accuracy for clustering.

import numpy
import sys
from munkres import Munkres

# Paths for the input files.
data_label_path = './data_label.txt'
clustering_result_path = './clustering_result.txt'
output_file_path = './clustering_accuracy.txt'

# Lists to hold contents of input files.
data_label = []
clustering_result = []

# Sets to verify count of labels and count of clusters match.
data_label_set = set()
clustering_result_set = set()

# Read data label file.
try:
    with open(data_label_path, 'r') as data_label_input:
        for current_label in data_label_input:
            data_label.append(int(current_label.split(' ')[0]))
            data_label_set.add(int(current_label.split(' ')[0]))
except:
    error_message = 'File + ' + data_label_path + ' not found.'
    exit(error_message)
data_label_input.close()

# Read clustering results file
try:
    with open(clustering_result_path, 'r') as clustering_result_input:
        for current_result in clustering_result_input:
            clustering_result.append(int(current_result.rstrip('\n')))
            clustering_result_set.add(int(current_result.rstrip('\n')))
except:
    error_message = 'File + ' + clustering_result_path + ' not found.'
    exit(error_message)
clustering_result_input.close()

explanation = """
Nick Petty
CAP6776 Homework 3

Accuracy = max (sum{Ck, Lm} T(Ck, Lm)) /n
Where n = number of data points, Ck denotes kth cluster, Lm is the mth class, and T(Ck, Lm) is the number of data points that belong to class m and are assigned to cluster k.  Because k and m refer to the number of classes in the data set, they must be equal.

Finding the maximum sum of T(Ck, Lm), when given T in matrix form, is a variation on the Assignment Problem.  Solving this problem via brute force will give a run time of m!, which is excessive.  Instead, the Munkres algorithm (or the Hungarian Algorithm) is used.  This gives a run time of m^3, which is much better.

To use the Munkres algorithm, the Python munkres package has been imported.
Package documentation: https://pypi.python.org/pypi/munkres/
The matrix from T(Ck, Lm) does not immediately work with this algorithm, as it is designed to find the minimum sum.  A second matrix, composed of a very large number minus each cell value in the T matrix must also be created.  This larger-valued matrix, when given to the algorithm, will then find the maximum sum.\n"""

# Set variables for calculation:

# Verify that count of labels matches count of clusters.  Find the number of classes m and clusters k.
if len(data_label_set) == len(clustering_result_set):
    m = len(data_label_set)
else:
# Write the output file and end the program.
    with open(output_file_path, 'w') as output_file:
        output_file.write(explanation)
        output_file.write("The number of data labels is not the same as the number of clusters.  Clustering accuracy cannot be calculated.")
    output_file.close()
    quit()

# Sum of T(Ck, Lm) values to maximize
max_sum = 0

# Number of data points.
n = len(data_label)

# Matrix to hold T(Ck, Lm)).
t_matrix = numpy.zeros((m, m), dtype=numpy.int)

# Matrix to hold large-valued t_matrix.
t_matrix_large = numpy.zeros((m, m), dtype=numpy.int)

# Generate T(Ck, Lm) and the large version as a copy.
for index in range(0, n):
    t_matrix[clustering_result[index] - 1][data_label[index] - 1] += 1
    t_matrix_large[clustering_result[index] - 1][data_label[index] - 1] += 1

# Fill the large version of T(Ck, Lm) with large values.
for i in range(0, m):
    for j in range(0, m):
        t_matrix_large[i][j] = sys.maxsize - t_matrix_large[i][j]

# Create a munkres object.
munkres_object = Munkres()

# Use the Munkres algorithm to find the location of cells that make the maximum sum.
max_sum_indices = munkres_object.compute(t_matrix_large)

# Save the values of the maximum sum cells.
max_sum_indices_values = []

# Determine maximum sum.
for row, column in max_sum_indices:
    max_sum += t_matrix[row][column]
    max_sum_indices_values.append(t_matrix[row][column])

# Write the output file.
with open(output_file_path, 'w') as output_file:
    output_file.write(explanation)
    output_file.write("\nThe number of data points, n: " + str(n) + "\n")
    output_file.write("\nT(Ck, Lm) as a k by m matrix, where each row is a cluster, and each column is a class label:\n")
    output_file.write(str(t_matrix) + "\n")
    output_file.write("\nT(Ck, Lm) cells and values that make up the maximum sum:\n")
    for i in range(0, m):
        output_file.write(str(max_sum_indices[i]) + " = " + str(max_sum_indices_values[i]) + "\n")

    output_file.write("-------------\n\t" + str(max_sum) + "\n")
    output_file.write("\nAccuracy for clustering then equals this maximum sum divided by n." + "\n")
    output_file.write(str(max_sum) + "/" + str(n) + " = " + str(max_sum / n))

output_file.close()


from django import forms

from . import models

class TinyMCEForm(forms.ModelForm):
    class Media:
        css = {
            'all': (
                '/static/css/autocomplete.css',
                'https://cdnjs.cloudflare.com/ajax/libs/at.js/1.5.2/css/jquery.atwho.min.css',
                )
            }
        js = (
            'https://cdnjs.cloudflare.com/ajax/libs/at.js/1.5.2/js/jquery.atwho.min.js',
            'https://cdnjs.cloudflare.com/ajax/libs/Caret.js/0.3.1/jquery.caret.min.js',
            '/static/js/tinymce/tinymce.min.js',
            )

class MonsterForm(TinyMCEForm):
    class Meta:
        model = models.Monster
        fields = [
            'name',
            'alignment',
            'size',
            'languages',
            'strength',
            'dexterity',
            'constitution',
            'intelligence',
            'wisdom',
            'charisma',
            'armor_class',
            'hit_points',
            'speed',
            'saving_throws',
            'skills',
            'creature_type',
            'damage_vulnerabilities',
            'damage_immunities',
            'damage_resistances',
            'condition_immunities',
            'senses',
            'challenge_rating',
            'content',
        ]

class NPCForm(TinyMCEForm):
    class Meta:
        model = models.NPC
        fields = [
            'name',
            'alignment',
            'size',
            'languages',
            'strength',
            'dexterity',
            'constitution',
            'intelligence',
            'wisdom',
            'charisma',
            'race',
            'armor_class',
            'hit_points',
            'speed',
            'saving_throws',
            'skills',
            'npc_class',
            'age',
            'height',
            'weight',
            'creature_type',
            'damage_vulnerabilities',
            'damage_immunities',
            'damage_resistances',
            'condition_immunities',
            'senses',
            'challenge_rating',
            'content',
        ]

class PlayerForm(TinyMCEForm):
    class Meta:
        model = models.Player
        fields = [
            'player_name',
            'character_name',
            'level',
            'xp',
            'race',
            'character_class',
            'background',
            'alignment',
            'armor_class',
            'initiative',
            'speed',
            'proficiency_bonus',
            'hit_points',
            'strength',
            'dexterity',
            'constitution',
            'intelligence',
            'wisdom',
            'charisma',
            'saving_throws',
            'skills',
            'age',
            'height',
            'weight',
            'languages',
            'personality',
            'ideals',
            'bonds',
            'flaws',
            'feats',
            'attacks',
            'spells',
            'proficiencies',
            'equipment',
            'notes',
        ]

class CopyMonsterForm(forms.ModelForm):
    class Meta:
        model = models.Monster
        fields = ['name']

class CopyNPCForm(forms.ModelForm):
    class Meta:
        model = models.NPC
        fields = ['name']

class CopyPlayerForm(forms.ModelForm):
    class Meta:
        model = models.Player
        fields = ['player_name']

class ImportMonsterForm(forms.ModelForm):
    class Meta:
        model = models.Monster
        fields = [
            'name',
        ]

class ImportNPCForm(forms.ModelForm):
    class Meta:
        model = models.NPC
        fields = [
            'name',
        ]

class SRDMonsterForm(forms.ModelForm):
    class Meta:
        model = models.Monster
        fields = ['name']

class SRDNPCForm(forms.ModelForm):
    class Meta:
        model = models.NPC
        fields = ['name']

MonsterFormSet = forms.modelformset_factory(
    models.Monster,
    form=MonsterForm,
    extra=0,
)

NPCFormSet = forms.modelformset_factory(
    models.NPC,
    form=NPCForm,
    extra=0,
)

class MonsterPublishForm(TinyMCEForm):
    class Meta:
        model = models.Monster
        fields = [
            'tavern_description',
        ]

class NPCPublishForm(TinyMCEForm):
    class Meta:
        model = models.NPC
        fields = [
            'tavern_description',
        ]

class PlayerPublishForm(TinyMCEForm):
    class Meta:
        model = models.Player
        fields = [
            'tavern_description',
        ]


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from measure_point import MeasurePoint
from measure_diameter import MeasureDiameter

piece = 1

pickPoints = False
interpolateMissingValues = False
meanGraph = False
multipleMeasures = False

data = pd.read_csv("../path/to/file/" + str(piece) + ".csv", header=None, names=["x", "y", "z"])

measures = np.zeros((3, 10)) #number of measurements, number of measures to be taken for each measurement
means = []
std = []
maxMinDiff = []

pickedPoints = []

def checkPoint(point, startingPoint, measurePoints):
        if not startingPoint.defined:
            if startingPoint.isPoint(point[0], point[1]):
                startingPoint.setRealPoint(point[0], point[1])
        for measurePoint in measurePoints:
            if not measurePoint.defined:
                if measurePoint.isPoint(point[0], point[1]):
                    measurePoint.setRealPoint(point[0], point[1])

def checkDiameter(diameter, startingDiameter, measureDiameters):
    if not startingDiameter.defined:
        if startingDiameter.isDiameter(diameter[0], diameter[1], diameter[2]):
            startingDiameter.setRealDiameter(diameter[2])
    for measureDiameter in measureDiameters:
        if not measureDiameter.defined:
            if measureDiameter.isDiameter(diameter[0], diameter[1], diameter[2]):
                measureDiameter.setRealDiameter(diameter[2])

def onClick(event):
    if event.button == 1 and event.dblclick:
        point = (round(event.xdata, 4), round(event.ydata, 4))
        pickedPoints.append(point)
        print(f"Point {len(pickedPoints)} picked: {point}")

def scan(y):
    run = data[data['y'] == (y / 1000)]

    runZ = run['z'].copy()
    runZ[runZ == '***'] = np.nan
    xStart = np.array(run['x'], dtype=np.float64)
    zStart = np.array(runZ, dtype=np.float64) / 1000
    runMat = np.matrix([xStart, zStart])

    if not pickPoints:
        try:
            points = np.genfromtxt("points_" + str(piece) + ".csv", delimiter=',')
        except FileNotFoundError:
            print("Pick points before run")
            return

        measurePoints = []
        measureDiameters = []
        for i in range(len(points)):
            point = points[i]
            if i == 0:
                startingPoint = MeasurePoint(point[0], point[1])
            elif i >= 1 and i <= 7:
                measurePoints.append(MeasurePoint(point[0], point[1]))
            elif i >= 8 and i <= 17:
                if i % 2 == 0:
                    lastPointX = point[0]
                else:
                    if i == 9:
                        startingDiameter = MeasureDiameter(lastPointX, point[0], point[1])
                    else:
                        measureDiameters.append(MeasureDiameter(lastPointX, point[0], point[1]))
            elif i == 18:
                lastDiam1 = point[0]
            elif i == 19:
                lastDiam2 = point[0]

        refIndices = np.where(((lastDiam1 <= xStart) & (xStart <= lastDiam2)) | ((startingDiameter.xStartRef <= xStart) & (xStart <= startingDiameter.xEndRef)))[0]
        xHorizontalRef = xStart[refIndices]
        zHorizontalRef = zStart[refIndices]
        nonNanIndices = np.logical_not(np.isnan(zHorizontalRef))
        xHorizontalRef = xHorizontalRef[nonNanIndices]
        zHorizontalRef = zHorizontalRef[nonNanIndices]
        m, q = np.polyfit(xHorizontalRef, zHorizontalRef, 1)

        a = -np.arctan(m)
        rotMat = np.matrix([[np.cos(a), -np.sin(a)], [np.sin(a), np.cos(a)]])
        rotatedRun = np.matmul(rotMat, runMat)

        run = pd.DataFrame(rotatedRun.transpose(), columns=['x', 'z'])
    else:
        run = pd.DataFrame(runMat.transpose(), columns=['x', 'z'])

    if interpolateMissingValues:
        dataGraph = run.copy()
        dataGraph = dataGraph.drop(dataGraph[np.isnan(dataGraph['z'])].index)
        xGraph = dataGraph['x']
        zGraph = np.array(dataGraph['z'], dtype=np.float64)
    else:
        xGraph = run['x']
        zGraphArray = run['z'].copy()
        zGraph = np.array(zGraphArray, dtype=np.float64)

    run = run.drop(run[np.isnan(run['z'])].index)

    runShift = run.shift(1)
    runShift.drop(runShift.index[:1], inplace=True)
    zShift = np.array(runShift['z'], dtype=np.float64)

    run = run.drop(run.index[:1])
    x = np.array(run['x'], dtype=np.float64)
    z = np.array(run['z'], dtype=np.float64)

    if not pickPoints:
        splitIndex = np.where((z < zShift - 0.1) | (z > zShift + 0.1))[0]
        splitIndex = np.insert(splitIndex, 0, 0)
        splitIndex = np.append(splitIndex, len(z))

        splitIndexDiameters = np.where((z < zShift - 0.02) | (z > zShift + 0.02))[0]
        if splitIndexDiameters[0] != 0:
            splitIndexDiameters = np.insert(splitIndexDiameters, 0, 0)
        if splitIndexDiameters[-1] != len(z):
            splitIndexDiameters = np.append(splitIndexDiameters, len(z))

        for i in range(len(splitIndex) - 1):
            xGroup = x[splitIndex[i]:splitIndex[i + 1]]
            zGroup = z[splitIndex[i]:splitIndex[i + 1]]
            checkPoint((xGroup[0], zGroup[0]), startingPoint, measurePoints)
            checkPoint((xGroup[-1], zGroup[-1]), startingPoint, measurePoints)

        zMeans = np.zeros(len(x))
        for i in range(len(splitIndexDiameters) - 1):
            zGroup = z[splitIndexDiameters[i]:splitIndexDiameters[i + 1]]
            mean = np.mean(zGroup)
            zMeans[splitIndexDiameters[i]:splitIndexDiameters[i + 1]] = mean
            xGroup = x[splitIndexDiameters[i]:splitIndexDiameters[i + 1]]
            checkDiameter([xGroup[0], xGroup[-1], mean], startingDiameter, measureDiameters)

        if startingPoint.defined:
            for i, measurePoint in enumerate(measurePoints):
                if measurePoint.defined:
                    measure = startingPoint.x - measurePoint.x
                    measures[y][i] = measure
                else:
                    print(f"Measure point {i + 1} not found for y={y / 1000}")

        if startingDiameter.defined:
            for i, measureDiameter in enumerate(measureDiameters):
                if measureDiameter.defined:
                    diameter = abs(measureDiameter.zMean - startingDiameter.zMean)
                    measures[y][len(measurePoints) + i] = diameter
                else:
                    print(f"Measure diameter {i + 1} not found for y={y / 1000}")

        if not multipleMeasures:
            print(measures[y])

            if meanGraph:
                xGraph = x
                zGraph = zMeans

            plt.plot(xGraph, zGraph)
            plt.xlim(np.nanmax(xGraph) + 3, np.nanmin(xGraph) - 3)
            plt.ylim(np.nanmin(zGraph) - 1, np.nanmax(zGraph) + 1)
            plt.show()

    else:
        fig, ax = plt.subplots()
        ax.plot(xGraph, zGraph)
        ax.set_xlim(np.nanmax(xGraph) + 3, np.nanmin(xGraph) - 3)
        ax.set_ylim(np.nanmin(zGraph) - 1, np.nanmax(zGraph) + 1)
        fig.canvas.mpl_connect('button_press_event', onClick)
        plt.show()
        if len(pickedPoints) == 20:
            np.savetxt("points_" + str(piece) + ".csv", pickedPoints, delimiter=',')
            print("Points file saved")

def main():
    if multipleMeasures:
        if pickPoints:
            print("PickPoints and MultipleMeasures cannot be used together")
            return

        for y in range(measures.shape[0]):
            scan(y)

        #np.savetxt("measures.csv", measures, delimiter=';')

        for dim in range(measures.shape[1]):
            allMeasures = measures[:, dim]
            allMeasures = allMeasures[allMeasures != 0]
            means.append(np.mean(allMeasures))
            std.append(np.std(allMeasures, ddof=1))
            maxMinDiff.append(np.max(allMeasures) - np.min(allMeasures))

        print("Means", means)
        print("Std", std)
        print("MaxMinDiff", maxMinDiff)
    else:
        scan(0) #editable

if __name__ == "__main__":
    main()


import sys;

def main(no):
    i=0;
    Digitsum=0;
    while (no != 0):
        Digitsum += no % 10;
        no = no // 10;
        i+=1;
    print("Addition of digits in no are: ",Digitsum);

if (__name__ == '__main__'):
    main(int(sys.argv[1]));


from learn_project import create_app
from learn_project.get_html import get_all_pages, get_html
from learn_project.url_scraping import get_products_urls, unfold_list
from learn_project.config import TARGET_URL
from learn_project.product_details import get_product_details
from learn_project.save_to_db import save_products

def parse():
    # принимает url категории товаров, возвращает список с html страницами этой категории
    lst_of_html_items = get_all_pages(TARGET_URL)
    print(f'total html pages {len(lst_of_html_items)}')

    # принимает список с str html страницами, возвращает список со списками url
    list_of_url_lists = [get_products_urls(html_item) for html_item in lst_of_html_items]
    print(f'total url lists {len(list_of_url_lists)}')
    print(f'url in first lists {len(list_of_url_lists[0])}')

    # принимает список со списками url, возвращает плоский список url
    flat_url_list = unfold_list(list_of_url_lists)
    print(f'total urls {len(flat_url_list)}')

    # принимает список url товаров
    app = create_app()
    for url in flat_url_list:
        product_html = get_html(url)  # собирает с них html
        with app.app_context():
            details = get_product_details(product_html)  # парсит
            save_products(*details.values())  # пишет результаты парсинга в бд
            print(f"сохранил {details['name']}")

if __name__ == '__main__':
    parse()


"""
Correspond au script exécutable du programme client. Utilise tous les 'Widgets' PyQt5 personnalisés de custom_widgets.
Choisir le mode (local ou serveur) avant d'exécuter.
"""
import json
import socket
import sys
from sys import argv

from client.custom_widgets import *

SERVER = "178.79.165.80"
LOCAL = 'localhost'
PORT = 4500
MODE = SERVER
print(argv)
if len(argv) >= 1 and argv[1] == "local":
    MODE = LOCAL
try:
    PORT = int(argv[2])
except (ValueError, IndexError):
    pass

class Server_handler(QObject):
    infos_server = pyqtSignal(str)

    @pyqtSlot()
    def handle_server(self):
        while True:
            msg_server = server.recv(1024).decode()
            self.infos_server.emit(msg_server)

class main_window(QMainWindow):
    start_comm = pyqtSignal()

    def __init__(self, server):

        QMainWindow.__init__(self)
        self.server = server
        self.table = None
        self.init_widget_home()
        self.functions_dict = {'init_table': self.init_table, 'new_game': self.new_game,
                               'update_table': self.update_table, 'end_game': self.end_game, 'action': self.action,
                               'name ok': self.widget_home.ask_if_ready, 'error name': self.widget_home.wrong_name,
                               'disconnect': self.disconnect}

        self.setObjectName("main_window")
        self.setWindowTitle("PSL Poker")
        self.setMinimumSize(QSize(300, 230))

        self.menu_bar = QMenuBar(self)
        self.menu_bar.setGeometry(QRect(0, 0, 900, 22))
        self.menu_bar.setObjectName("menu_bar")

        self.server_handler = Server_handler()
        self.server_handler_thread = QThread()
        self.server_handler.moveToThread(self.server_handler_thread)
        self.server_handler_thread.start()

        self.start_comm.connect(self.server_handler.handle_server)
        self.server_handler.infos_server.connect(self.server_to_functions)

        self.show()
        self.start_comm.emit()

    def init_widget_home(self):

        self.resize(430, 300)
        self.widget_home = widget_home(server=server)
        self.setCentralWidget(self.widget_home)

    def init_widget_game(self):
        self.resize(1000, 700)
        self.client_name = self.widget_home.client_name
        self.setWindowTitle(f"PSL Poker - {self.client_name}")
        self.widget_game = widget_game(server=server)
        self.setCentralWidget(self.widget_game)

    @pyqtSlot(str)
    def server_to_functions(self, msg_server):

        serv_inf = json.loads(msg_server)
        print(f"\nFrom server to client :\n")
        for key, value in serv_inf.items():
            print(f"{key} : {value}")
        self.functions_dict[serv_inf['flag']](serv_inf)

    def init_table(self, serv_inf):
        players, time_to_play = serv_inf['players_data'], 30
        for i in range(len(players)):
            p = players[i]
            players[i] = Player(p['name'], p['id'], p['stack'], p['is_player'])
        self.init_widget_game()
        self.table = Table(players=players, widget_game=self.widget_game, time_to_play=time_to_play)
        self.table.show_used_widgets()
        self.repaint()
        print('Table has been initiated')

    def new_game(self, serv_inf):
        players, table_cards, dealer_id = self.table.players, self.table.widget_table.table_cards, serv_inf['dealer_id']
        client_cards = serv_inf['client_cards']
        sb, bb = serv_inf['blinds']
        for player in players:
            player.widget_player.is_not_speaking_and_did_not_win()
            if player.id == serv_inf['speaker_id']:
                player.widget_player.is_speaking()
            player.is_folded = player.is_all_in = False
            player.set_ogb(0)
            player.show_dealer_button(player.id == dealer_id)
            if player.is_client:
                player.widget_player.p_0_cards.set_cards(card1=client_cards[0], card2=client_cards[1])
            player.show_cards(True)
            for blind in [sb, bb]:
                if player.id == blind['player_id']:
                    player.set_ogb(blind['on_going_bet'])
                    player.set_stack(blind['player_stack'])
        table_cards.new_game()
        print('New_game has been started')

    def update_table(self, serv_inf):
        infos_players = serv_inf['infos_players']
        for infos_player in infos_players:
            player = self.table.get_player_from_id(infos_player['player_id'])
            player.set_ogb(infos_player['on_going_bet'])
            player.set_stack(infos_player['player_stack'])
            if infos_player['is_folded']:
                if not player.is_folded:
                    player.folds()
            if infos_player['is_all_in']:
                if not player.is_all_in:
                    player.all_in()
            if player.id == serv_inf['speaker_id']:
                player.widget_player.is_speaking()
            else:
                player.widget_player.is_not_speaking_and_did_not_win()
        self.table.set_pot(serv_inf['pot'])
        self.table.widget_table.table_cards.set_cards(serv_inf['table_cards'])
        print('Table has been updated')

    def action(self, serv_inf):
        stack, ogb = self.table.client_player.stack, self.table.client_player.ogb
        amount_to_call = serv_inf['amount_to_call']
        self.table.widget_game.action(stack, ogb, amount_to_call)
        print('Action has initiated')

    def end_game(self, serv_inf):
        for player in self.table.players:
            player.widget_player.is_not_speaking_and_did_not_win()
        for winner_id in serv_inf['winners_id']:
            winner = self.table.get_player_from_id(winner_id)
            winner.widget_player.won()
        if serv_inf['show_cards']:
            self.widget_end_game = widget_end_game(serv_inf['cards'])
        self.table.set_pot(0)
        print('Game has ended')

    def disconnect(self, serv_inf):
        print('Player has been disconnected')
        app.quit()

    def resizeEvent(self, e):
        w = self.width()
        self.setFixedHeight(0.7 * w)

class Player:
    def __init__(self, name, id, stack, is_client=False):
        self.name = name
        self.ogb = 0
        self.stack = stack
        self.is_client = is_client
        self.is_folded = self.is_all_in = False
        self.id = id

    def set_attributes(self, widget_p, widget_f):
        self.widget_player = widget_p
        self.widget_front = widget_f
        self.widget_player.label_name.setText(self.name)
        self.set_stack(self.stack)
        if self.is_client:
            self.widget_player.p_0_cards.set_name(self.name)

    def show_dealer_button(self, value):
        if value:
            self.widget_front.label_dealer.show()
        else:
            self.widget_front.label_dealer.hide()

    def show_cards(self, value):
        if value:
            self.widget_player.show_cards()
        else:
            self.widget_player.hide_cards()

    def set_ogb(self, value):
        self.ogb = value
        if value > 0:
            self.widget_front.widget_ogb.label.setText(str(value))
            self.widget_front.widget_ogb.show()
        else:
            self.widget_front.widget_ogb.hide()

    def set_stack(self, value):
        self.stack = value
        self.widget_player.label_stack.setText(str(value))

    def folds(self):
        self.widget_player.hide_cards()
        self.is_folded = True

    def all_in(self):
        self.widget_player.is_all_in()
        self.is_all_in = True

class Table:
    def __init__(self, players, widget_game, time_to_play):
        self.players = players
        self.nb_players = len(self.players)
        self.time_to_play = time_to_play
        self.widget_game, self.widget_table = widget_game, widget_game.widget_table
        for player in self.players:
            if player.is_client:
                self.client_player = player
        self.base_id = self.client_player.id
        self.connect_players_to_widgets()

    def connect_players_to_widgets(self):
        """On donne ici le table_id à chaque joueur de la table, et on donne à chaque joueur ses attributs
        wp et wf (widget_player et widget_front)"""

        ind_client = self.players.index(self.client_player)
        self.players.sort(key=lambda x: x.id)
        self.players = self.players[ind_client:] + self.players[:ind_client]
        for ind in range(self.nb_players):
            self.players[ind].table_id = table_ids_order[ind]
            ordered_widgets = sorted(table_ids_order[:self.nb_players])
            widget_id = ordered_widgets[ind]
            self.players[ind].set_attributes(widget_p=self.widget_table.widget_players[widget_id],
                                             widget_f=self.widget_table.widget_fronts[widget_id])

    def show_used_widgets(self):
        for player in self.players:
            player.widget_front.show()
            player.widget_player.show()

    def get_player_from_id(self, id):
        for player in self.players:
            if player.id == id:
                return player

    def set_pot(self, value):
        if value > 0:
            self.widget_table.table_cards.widget_pot.label.setText(str(value))
            self.widget_table.table_cards.widget_pot.show()
        else:
            self.widget_table.table_cards.widget_pot.hide()

def send_server(dico, server):
    dico = json.dumps(dico)
    print('From client to server : ', dico)
    server.send(dico.encode())

table_ids_order = [0, 4, 3, 2, 5, 1, 6]

if __name__ == '__main__':
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.connect((MODE, PORT))
    app = QApplication(sys.argv)
    game_window = main_window(server)
    sys.exit(app.exec_())


import pandas as pd
import geopandas as gpd
import numpy as np
import matplotlib.pyplot as plt
import sys
import folium
import branca
from features import *
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from folium.plugins import MeasureControl

class mapfun(object):

	def __init__(self, x:float, y:float, zoom:int=10):
		self.map = folium.Map(location=[y,x], zoom_start=zoom)

	def add_tiles(self, tile_type:str='World_Imagery', services:str=''):
		'''
		add different tiles to the interactive map
		inputs
			folmap = intitialized interactive map
			Defaults:
				- tile type = esri tile layer name (World_Imagery, USA_Topo_Maps, World_Shaded_Relief,
													World_Street_Map)
				- services  = access service sub dir or choose other ones (/Canvas,/Elevation,/Ocean,
																			/Polar, etc)
				*note*  : if you change services then the tile needs to be changed according to the service
							you want.
		'''
		EsriImagery = "https://server.arcgisonline.com/ArcGIS/rest/services"\
					f"{services}/{tile_type}/MapServer/"\
					"tile/{z}/{y}/{x}"
		EsriAttribution = "Tiles © Esri — Source: Esri, i-cubed,"\
					" USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP"\
					", UPR-EGP, and the GIS User Community"
		folium.TileLayer(tiles=EsriImagery, attr=EsriAttribution, name=tile_type).add_to(self.map)
		return self

	def add_cm_points(self, gdf0:gpd.GeoDataFrame, info:list, name:list, cmap:list, add_table:bool=True):
		'''
		 adds points with colormap to folium map
		 inputs:
		 	gdf0:				geopandas.GeoDataFrame
			cmap:				list of colors
			add_table :         choose if you would like to add a table to points
			info:  				adds descriptions in table format
								to polygons
			name:				list of the names of the polygons

		'''

		if add_table:
			for idx in  gdf0.index:
				iframe=branca.element.IFrame(html=info[idx], width=box_width(info[idx]),
											height=box_height(info[idx]))
				popup = folium.Popup(iframe)
				self.map.add_child(folium.CircleMarker(location=[gdf0.loc[idx]['geometry'].y,
											 gdf0.loc[idx]['geometry'].x],
											 popup= popup,radius=4, fill=True, weight=4,
											  color=mpl.colors.to_hex(cmap),
											  fill_color=mpl.colors.to_hex(cmap), fill_opacity=1))
		else:
			for idx in  gdf0.index:
				self.map.add_child(folium.CircleMarker(location=[gdf0.loc[idx]['geometry'].y,
											 gdf0.loc[idx]['geometry'].x],
											 radius=4, fill=True, weight=4,
											  color=mpl.colors.to_hex(cmap),
											  fill_color=mpl.colors.to_hex(cmap), fill_opacity=1))
		return self

	def add_point(self, gdf0:gpd.GeoDataFrame, info:list, name:list, color:str='red',\
			fillcolor:str='red',data:list=None,add_table:bool=True):
		'''
		 adds points to folium map
		 inputs:
		 	gdf0:				geopandas.GeoDataFrame

			add_table :         choose if you would like to add a table to points
			info:  				adds descriptions in table format
								to points
			name:				list of the names of the points

		'''
		sID=name

		if type(color) == list:
			color = colormap(data)
			fillcolor = colormap(data)
		if add_table:
			for idx in  gdf0.index:
				iframe=branca.element.IFrame(html=info[idx], width=box_width(info[idx]),
											height=box_height(info[idx]))
				popup = folium.Popup(iframe)
				self.map.add_child(folium.CircleMarker(location=[gdf0.loc[idx]['geometry'].y,
											 gdf0.loc[idx]['geometry'].x],
											 popup= popup,radius=4, fill=True, weight=4,
											  color=color,fill_color=fillcolor, fill_opacity=1))
		else:
			for idx in  gdf0.index:
				self.map.add_child(folium.CircleMarker(location=[gdf0.loc[idx]['geometry'].y,
											 gdf0.loc[idx]['geometry'].x],
											 radius=4, fill=True, weight=4,
											  color=color,fill_color=fillcolor, fill_opacity=1))
		return self

	def add_lines(self, gdf0:gpd.GeoDataFrame, info:list, name:list,\
				 color:str='blue',fillcolor:str='blue',add_table:bool=True):
		'''
		 adds lines to folium map
		 inputs:
		 	gdf0:				geopandas.GeoDataFrame

			add_table :         choose if you would like to add a table to points
			info:  				adds descriptions in table format
								to lines
			name:				list of the names of the lines

		'''
		sID=name
		if add_table:
			for idx in  gdf0.index:
				geometry =  gdf0.loc[idx].geometry
				if geometry.type == 'MultiLineString':

					iframe=branca.element.IFrame(html=info[idx], width=box_width(info[idx]),
						height=box_height(info[idx]))
					popup = folium.Popup(iframe)
					for line in gdf0.geometry[idx]:
						x = line.coords.xy[0]
						y = line.coords.xy[1]
						line_points = zip(y,x)
						style_function = lambda x :{'fillColor': fillcolor,'color': color,'opacity':0.6,'fillOpacity': 0.4}
						geojson = folium.GeoJson(line,name=name[idx],style_function=style_function).add_to(self.map)
						geojson.add_child(popup)
				else:
					iframe=branca.element.IFrame(html=info[idx], width=box_width(info[idx]),
												height=box_height(info[idx]))
					popup = folium.Popup(iframe)

					#assert geometry.type  != 'MultiLineString', "MultiLineString in dataset, convert to line in GIS before continuing"

					x = geometry.coords.xy[0]
					y = geometry.coords.xy[1]
					style_function = lambda x :{'fillColor': fillcolor,'color': color,'opacity':0.6,'fillOpacity': 0.4}
					line_points = zip(y,x)
					geojson = folium.GeoJson(gdf0.geometry[idx],name=name[idx],style_function=style_function).add_to(self.map)
					geojson.add_child(popup)
		else:
			for idx in  gdf0.index:

				geometry =  gdf0.loc[idx].geometry
				if geometry.type == 'MultiLineString':

					for line in gdf0.geometry[idx]:
						x = line.coords.xy[0]
						y = line.coords.xy[1]
						line_points = zip(y,x)
						style_function = lambda x :{'fillColor': fillcolor,'color': color,'opacity':0.6,'fillOpacity': 0.4}
						geojson = folium.GeoJson(line,name=name[idx],style_function=style_function).add_to(self.map)

				else:
					x = geometry.coords.xy[0]
					y = geometry.coords.xy[1]
					style_function = lambda x :{'fillColor': fillcolor,'color': color,'opacity':0.6,'fillOpacity': 0.4}
					line_points = zip(y,x)
					geojson = folium.GeoJson(gdf0.geometry[idx],name=name[idx],style_function=style_function).add_to(self.map)

		return self

	def add_polygon(self, gdf0:gpd.GeoDataFrame, info:list, name:list,\
				 color:str='black',fillcolor:str='black',add_table:bool=True):
		'''
		 adds polygons to folium map
		 inputs:
		 	gdf0:				geopandas.GeoDataFrame

			add_table :         choose if you would like to add a table to points
			info:  				adds descriptions in table format
								to polygons
			name:				list of the names of the polygons

		'''
		if add_table:

			for idx in  gdf0.index:
				iframe=branca.element.IFrame(html=info[idx], width=box_width(info[idx]),
											height=box_height(info[idx]))
				popup = folium.Popup(iframe)
				style_function = lambda x :{'fillColor': fillcolor,'color': color,'opacity':0.6,'fillOpacity': 0.4}

				geojson = folium.GeoJson(gdf0.geometry[idx],name=name[idx],style_function=style_function).add_to(self.map)
				geojson.add_child(popup)
		else:
			for idx in  gdf0.index:

				style_function = lambda x :{'fillColor': fillcolor,'color': color,'opacity':0.6,'fillOpacity': 0.4}

				geojson = folium.GeoJson(gdf0.geometry[idx],name=name[idx],style_function=style_function).add_to(self.map)
		return self

	def add_extra(self):
		folium.LayerControl().add_to(self.map)
		self.map.add_child(MeasureControl())
		return self

#---------- extra attribute functions that support the functions above---------------

def colormap(data:list, cmap_type:str='jet', vmin=0):
	'''
	 calculates colors based on the data and cmap
	'''
	cmap = cm.get_cmap(cmap_type)
	normalize = mpl.colors.Normalize(vmin=vmin, vmax=max(data))
	colors = [cmap(normalize(value)) for value in data]

	return colors

def colors():
	'''
	List of colors for branca colorbar
	needs to be updated 7/12
	'''
	colors = ['#8000FF','#5500FF','#4000FF','#1500FF','#0000FF','#002AFF','#0055FF',
	'#0080FF','#00AAFF','#00D4FF','#00FFFF','#00FFAA','#00FF80','#00FF2A','#2AFF00',
	'#80FF00','#AAFF00','#D4FF00','#FFFF00','#FFD400','#FFAA00','#FF8000','#FF6A00',
	'#FF4000','#FF2A00','#FF1500','#FF0000']
	return colors

def add_cbar(data:list,folmap:folium.folium.Map,caption:str='HWM(ft) above NAVD88', vmin=0):
	'''
	adds a colorbar to a folium map
	'''
	colormap = branca.colormap.StepColormap(colors=colors(),vmin=vmin,vmax=np.max(round(data,1)))
	colormap.caption = caption
	colormap.add_to(folmap)

	return folmap

def box_width(descriptions:str):
	'''
	automatically sets the width of the html box based on the inputs given
	'''
	width = 175
	num_columns = find_all(descriptions,'COL width=')
	for i in num_columns:
		width += int(descriptions[i:(i+20)].split('"')[1].split('%')[0])
	return width

def box_height(descriptions:str):
	'''
	automatically adjusts the height of the html box
	'''
	height = 100
	num_rows = find_all(descriptions,'<TR>')
	height = height+(len(num_rows)*20)
	return height

def quick_transform(vector, incrs):
	'''
	sets the crs projection for the vector
	'''
	vector.crs = incrs
	return vector.to_crs({'init': 'epsg:4326'})

def get_centroid(vector):
	'''
	finds the center points in x,y from a geopandas.GeoDataFrame
	'''
	geom = vector.geometry
	xpoints = [float(v.x) for v in geom]
	ypoints = [float(v.y) for v in geom]
	return np.mean(xpoints), np.mean(ypoints)


import socket
import sys
import datetime

from threading import Thread
from time import sleep

from database.database import Database

class Server:
    def __init__(self):
        print("Data Server Created")
        self.received_data = []

    def encode(self, data):
        return data.encode("utf-8")

    def decode(self, data):
        return data.decode("utf-8")

    def request_measurements(self):
        while 1:
            now = datetime.datetime.now()
            file_name = "./storage/{}{}{}".format(now.day, now.month, now.year)
            db = Database(file_name)

            response = "ERROR: Response Not Defined"
            try:
                host = "192.168.0.13"  # location of PIS
                port = 8501  # PIS port
                request = "hi"  # irrelevant, PIS always returns everything
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.connect((host, port))
                sock.send(self.encode(request))
                response = sock.recv(1024)
                response = self.decode(response)
                db.insert(response)  # insert into DB
                # response is the readings, append them onto end of list
                self.received_data.append(response)
                sock.close()
            except OSError as os_error:
                print(os_error)
                response = "ERROR: Could Not Connect to Data Server at {}:{}".format(
                    host, port)

            sleep(1)

    def start_server(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if(len(sys.argv) > 1):
            port = sys.argv[1]
        else:
            port = 15000

        s.bind(('0.0.0.0', int(port)))
        print("Server Started on Port", port)
        s.listen(5)
        while 1:
            conn, addr = s.accept()
            conn_thread = Thread(target=self.handle_conn, args=(conn,))
            conn_thread.start()

    def handle_conn(self, conn):
        data = conn.recv(1024)
        data = self.decode(data)

        response = data
        args = data.split(" ")
        method_type = args[0]
        if(method_type == "GET_DATA"):
            property_ = args[1]  # voltage, current power etc
            if(property_ == "A"):  # get ALL
                quantity = int(args[2])  # how many
                total = len(self.received_data)
                if(quantity <= total):
                    response = ""
                    start = total - quantity
                    for i in range(start, total):
                        response = response + self.received_data[i]
                else:
                    response = "ERROR: Quantity cannot exceed total"
        response = self.encode(response)
        conn.send(response)


'''
Given an integer array of N elements. You need to find the maximum sum of two elements such that sum is closest to zero.

Example 1:

Input:
N = 3
arr[] = {-8 -66 -60}
Output: -68
Explanation: Sum of two elements closest to
zero is -68 using numbers -60 and -8.

Example 2:

Input:
N = 6
arr[] = {-21 -67 -37 -18 4 -65}
Output: -14
Explanation: Sum of two elements closest to
zero is -14 using numbers -18 and 4.

Note : In Case if we have two of more ways to form sum of two elements closest to zero return the maximum sum.

Your Task:
You don't need to read input or print anything. You just need to complete the function closestToZero()
which takes an array arr[] and its size n as inputs and returns the maximum sum closest to zero that can
be formed by summing any two elements in the array.

Expected Time Complexity: O(N*logN).
Expected Auxiliary Space: O(1).
'''

def closestToZero(self, arr, n):
    # your code here

    ans = 999999

    # for i in range(n):
    #     for j in range(i+1,n):
    #         val = arr[i]+arr[j]

    #         if abs(val) < abs(ans):
    #             ans = val
    # return ans

    arr.sort()
    l = 0
    r = n-1

    while (l < r):
        val = arr[l]+arr[r]

        if abs(val) < abs(ans):
            ans = val

        if abs(val) == abs(ans):
            ans = max(ans, val)

        if val == 0:
            return 0

        if val < 0:
            l += 1

        if val > 0:
            r -= 1

    return ans


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

from filereader import FileReader
from collections import Counter

def tongjinetype():
    filereader = FileReader("../NE_INFO.csv")
    attridx = filereader.getattridx("NE_CAT_ID")
    trandata = {}
    while True:
        tmptran = filereader.readtransection()
        if tmptran is None:
            break
        summary = tmptran[attridx]
        if summary not in trandata:
            trandata[summary] = 0
        trandata[summary] += 1
    import pprint
    pp = pprint.PrettyPrinter(indent=4)
    pp.pprint(trandata)

    # valuelist = trandata.values()
    # valuelist.sort()
    # c = Counter(valuelist)
    # keylist = c.keys()
    # keylist.sort()
    # for key in keylist:
    #     print key,"\t:\t",c[key]
    #
    # itemslist = trandata.items()
    # itemslist.sort(key=lambda v:v[1],reverse=True)
    # for key,value in itemslist:
    #     print key
    #     print value
    #     raw_input()

    # print valuelist

if __name__ == "__main__":
    tongjinetype()


import os
import json
import pandas as pd

def read_json_data(data_path : str, verbose=True):
    '''reads the contents of a json file, returns the content as a pandas dataframe to facilitate analysis
       json structure: {"data": [{"text": str, "label": str}]}'''

    # later on a check can be implemented to see if the parsed, tokenized and downsampled data is available.
    # but for the purpose of this task with small size, the performance is not affected by redoing it.

    json_path = __get_json_file_path(data_path)

    with open(json_path, encoding='utf8') as file:
        json_data = json.load(file)

    json_data = json_data['data']

    data_frame = pd.DataFrame.from_dict(json_data)

    if verbose:
        print('Parsed json file: ', len(data_frame), 'rows.')

    return data_frame

def store_datasets_as_csv(train : pd.DataFrame, dev : pd.DataFrame, test : pd.DataFrame, path_to_store : str):
    '''stores the provided pandas subsets as csv files'''

    if not os.path.isdir(path_to_store):
        os.makedirs(path_to_store)

    train.to_csv(os.path.join(path_to_store, 'train.csv'), header=False, index=False)
    dev.to_csv(os.path.join(path_to_store, 'dev.csv'), header=False, index=False)
    test.to_csv(os.path.join(path_to_store, 'test.csv'), header=False, index=False)

def __get_json_file_path(data_path):
    '''a helper method to get the name of the json file in the directory'''

    if not os.path.exists(data_path):
        raise ValueError("Data path doesn't exist.")

    json_files = [file for file in os.listdir(data_path) if file.endswith('.json')]

    if not len(json_files):
        raise ValueError('No json files in the provided path.')
    elif len(json_files) > 1:
        raise ValueError('Multiple json files exist. Please keep only one json file in this directory.')

    json_path = os.path.join(data_path, json_files[0])

    return json_path


class B_plus_tree_node:

    def __init__(self, is_leaf = True):

        self.keys = []
        self.children = []
        self.is_leaf = is_leaf
        self.next_leaf = None

    # currently unused and non-functional
    def add_node(self, key, new_node):

        for i in range(len(self.keys)):
            if key < self.keys[i]:
                #self.children[i] = new_node # change to insert at i
                self.children = self.children[0:i] + [key] + self.children[i:]
                return

        self.children.append(new_node)

    def __repr__(self):
        return str(self.keys)

class B_plus_tree:

    def __init__(self,order = 4):

        self.root = None
        self.size = 0
        self.order = order

    def is_empty(self):
        return self.size == 0

    def contains(self, item):

        if self.is_empty():
            return False

        current_node = self.root
        while current_node.is_leaf == False:
            print(current_node)
            child_index = 0
            while child_index < len(current_node.keys) and item >= current_node.keys[child_index]:
                print(item, " is greater than or equal to", current_node.keys[child_index])
                child_index += 1

            current_node = current_node.children[child_index]
        print("current node is",current_node, "checking for", item)
        print("current node leaf?", current_node.is_leaf)
        return item in current_node.keys

    def all_values(self):

        to_return = []
        current_node = self.root
        while current_node.is_leaf == False:
            current_node = current_node.children[0]

        while current_node.next_leaf:

            for item in current_node.keys:
                to_return.append(item)

            current_node = current_node.next_leaf

        for item in current_node.keys:
            to_return.append(item)

        return to_return

    def insert(self,item):

        # empty tree creates root
        if self.is_empty():
            self.root = B_plus_tree_node()
            self.root.keys.append(item)
            self.size += 1
        else:
            current_node = self.root
            eject = self._insert_helper(current_node, item)
            self.size += 1
            if eject != None:
                self.root = B_plus_tree_node(False)
                self.root.keys.append(eject[0])
                self.root.children.append(eject[2])
                self.root.children.append(eject[1])
                print("new root is",self.root)
                print("children are",self.root.children)

    ''' From Wikipedia B+ tree article
    Perform a search to determine what bucket the new record should go into.
    If the bucket is not full (at most b − 1) entries after the insertion), add the record.
    Otherwise, before inserting the new record
    split the bucket
    original node has ⎡(L+1)/2⎤ items
    new node has ⎣(L+1)/2⎦ items
    Move ⎡(L+1)/2⎤-th key to the parent, and insert the new node to the parent.
    Repeat until a parent is found that need not split.
    If the root splits, treat it as if it has an empty parent and split as outline above.'''
    def _insert_helper(self, current_node, item):
        """
        Recursive helper function that adds new item to tree.
        Always adds item to leaf node, then pushes middle value up if needed.
        """

        if current_node.is_leaf:

            print("current node is:",current_node)
            current_node.keys.append(item)
            keys = current_node.keys
            index = len(keys) - 1
            while index > 0 and keys[index] < keys[index - 1]:
                print(item, "is smaller than",keys[index - 1])
                print("swapping")
                keys[index], keys[index - 1] = keys[index - 1], keys[index]
                print(current_node)
                index -= 1
            # if number of keys is greater than maximum number of keys, eject middle key to parent
            if len(keys) >= self.order:
                print("current node full, ejecting")
                print("current node before ejection:",current_node)
                mid = len(keys) // 2
                #eject = keys.pop(len(keys)//2)
                eject = keys[mid]
                print("ejecting",eject)
                new_node = B_plus_tree_node()
                new_node.keys = keys[mid:]
                new_node.next_leaf = current_node.next_leaf
                current_node.keys = keys[0:mid]
                current_node.next_leaf = new_node
                print("new node (right)",new_node)
                print("old node (left)",current_node)
                return (eject, new_node, current_node)
            else:
                return None

        else:
            child_index = len(current_node.keys)
            for i in range(len(current_node.keys)):
                print("item:",item,"key:",current_node.keys[i])
                if item <= current_node.keys[i]:
                    print(item," is less than",current_node.keys[i])
                    child_index = i
                    break
            print("child index is",child_index, "node will be",current_node.children[child_index])
            child_node = current_node.children[child_index]
            ejected_item = self._insert_helper(child_node, item)

            if ejected_item == None:
                return None
            else:
                print("ejected items",ejected_item)
                print("current_node",current_node)
                print("current_node children are", current_node.children)
                to_add = ejected_item[0]
                new_node = ejected_item[1]
                old_node = ejected_item[2]
                current_node.children.insert(child_index+1,new_node)
                print("current_node children",current_node.children)
                # should now handle next_leaf when at leaf level
                #if old_node.is_leaf:
                #   old.node.next_leaf = new_node

                current_node.keys.append(to_add)
                keys = current_node.keys
                index = len(keys) - 1
                while index > 0 and keys[index] < keys[index - 1]:
                    keys[index], keys[index - 1] = keys[index - 1], keys[index]
                    index -= 1
                # if number of keys is greater than maximum number of keys, eject middle key to parent
                if len(keys) >= self.order:
                    print("current node full, ejecting")
                    print("current node before ejection:",current_node)
                    mid = len(keys) // 2
                    #eject = keys.pop(len(keys)//2)
                    eject = keys[mid]
                    print("ejecting*****",eject)
                    new_node = B_plus_tree_node(False)
                    new_node.keys = keys[mid+1:]
                    new_node.children = current_node.children[mid+1:]
                    current_node.keys = keys[0:mid]
                    current_node.children = current_node.children[0:mid+1]
                    print("new node (right)",new_node)
                    print("old node (left)",current_node)
                    return (eject, new_node, current_node)
                else:
                    return None

    def delete(self, item):

        if self.is_empty():
            raise ValueError("Tree is empty!")
        else:
            current_node = self.root
            key_changes = self._delete_helper(current_node, item)
            self.size -= 1

    # first attempt at delete oh lawdy this sucks
    '''
    def _delete_helper(self, current_node, item):

        if current_node.is_leaf:

            removed = None
            for i in range(len(current_node.keys)):
                if current_node.keys[i] == item:
                    removed = current_node.keys.pop(i)
                    break
            # no item removed, item not in tree
            if removed == None:
                print("value not found")
                return (None, False)
                #raise ValueError(item, "not in tree!")

            else:
                # check if work needs to be done to fix tree
                if len(current_node.keys) == 0:
                    return (removed, True)
                else:
                    return (removed, False)

        else:
            child_index = len(current_node.keys)
            for i in range(len(current_node.keys)):
                #print("item:",item,"key:",current_node.keys[i])
                if item <= current_node.keys[i]:
                    #print(item," is less than",current_node.keys[i])
                    child_index = i
                    break
            print("child index is",child_index, "node will be",current_node.children[child_index])
            child_node = current_node.children[child_index]
            returned_value = self._delete_helper(child_node, item)
            if returned_value[1] == False:
                if returned_value[0] in current_node.keys:
                    # need to change index keys in current_node to fix tree structure
                    print("why is this so hard")
                return None
            else:
                if child_node.is_leaf:
                    # need to fix tree, start by checking siblings
                    left_sibling = current_node.children[child_index - 1] if child_index > 0 else None
                    if left_sibling:
                        if len(left_sibling.keys) >= 2:
                            # left sibling has enough to steal from
                            value = left_sibling.keys.pop()
                            child_node.keys.insert(0,value)
                            current_node.keys[child_index - 1] = value
                            return (removed, False)
                    right_sibling = current_node.children[child_index + 1] if child_index < len(current_node.children) - 1 else None
                    if right_sibling:
                        if len(right_sibling.keys) >= 2:
                            # left sibling has enough to steal from
                            value = right_sibling.keys.pop(0)
                            child_node.keys.append(value)
                            current_node.keys[child_index] = value
                            return (removed, False)
                    # no siblings can give value, merging necessary'''

def test_bptree():

    tree = B_plus_tree(5)
    items = [40,30,20,50,60,10,70,80,15,25,45,85]
    for item in items:
        print("inserting", item)
        tree.insert(item)
        print("root",tree.root)
        print("children",len(tree.root.children))
        for child in tree.root.children:
            print(child)
            print("children are",child.children)
            for child2 in child.children:
                print(child2)
                print("next leaf is",child2.next_leaf)
            print("next leaf is",child.next_leaf)

    print("\n\n *********** DONE INSERTING")
    print(tree.contains(60))
    print(tree.contains(40))
    print(tree.contains(75))
    print(tree.all_values())
    tree.delete(40)

if __name__ == '__main__':
    test_bptree()


import cv2
import numpy as np
import os
import face_recognition
import json

from multiprocess import pool

import csv

def savecsv(toCSV) :

    csv_columns =toCSV[0].keys()
    csv_file="Datadet.csv"
    try:
        with open(csv_file, 'w') as csvfile:
            writer = csv.DictWriter(csvfile, fieldnames=csv_columns)
            writer.writeheader()
            for data in toCSV:
                writer.writerow(data)
    except IOError:
        print("I/O error")

def regr(ks , camera) :
    if not os.path.exists("data"):
        os.makedirs("data")   # this is the location of pictures of the students , used for backup

    if not os.path.exists("json"):
        os.makedirs("json")   # all json files will be stored here

    direc = "data/"
    cap = cv2.VideoCapture(camera)  #'http://192.168.137.163:4747/mjpegfeed'  it changes every time a connectipn is made

    while True :
        _, frame = cap.read()
     # frame size
        x1 = int(10)
        y1 = 10
        x2 = int(frame.shape[1])
        y2 = int(frame.shape[1])

        cv2.rectangle(frame, (x1-1, y1-1), (x2+1, y2+1), (255,0,0) ,1)

        font = cv2.FONT_HERSHEY_SIMPLEX
        cv2.imshow("Frame", frame)

        interrupt = cv2.waitKey(10)

        if  interrupt & 0xFF ==ord('1') :

            try :
                fi = face_recognition.face_encodings(frame)[0]
                cv2.imwrite(direc +ks+'.jpg', frame)
                cap.release()
                cv2.destroyAllWindows()
                return frame , fi

            except IndexError :
                print("ERROR")

def resu(frame ) :

     with open('Datadet.csv', 'r', encoding='utf-8') as csvfile:
                #sniff to find the format
                fileDialect = csv.Sniffer().sniff(csvfile.read(1024))
                csvfile.seek(0)
                #create a CSV reader
                myReader = csv.reader(csvfile, dialect=fileDialect)
                #read each row
                print(myReader)


from app.models import db, Channel, ChannelMessage, ChannelMember

def seed_channels():
    channels = [{'name': 'General', 'server_id': 1},{'name': '2021-11-15-online', 'server_id': 1},{'name': '2021-11-15-online-questions', 'server_id': 1},{'name': 'General', 'server_id': 2},{'name': 'NineTails', 'server_id': 2},{'name': 'Itachi SuS?', 'server_id': 2},{'name': 'General', 'server_id': 3},{'name': 'MoM?', 'server_id': 3},{'name': 'Yaegerists', 'server_id': 3}]
    for channel in channels:
        new_channel = Channel(name=channel['name'], server_id=channel['server_id'])
        db.session.add(new_channel)

    db.session.commit()

def seed_dm_channels():
    channels = [{'dm_channel':True,'owner_id': 2}]
    for channel in channels:
        new_channel = Channel(owner_id=channel['owner_id'], dm_channel=channel['dm_channel'])
        db.session.add(new_channel)

    db.session.commit()

def seed_channel_members():
    channel_members = [{'channel_id': 10, 'user_id': 2}, {'channel_id': 10, 'user_id': 19}]

    for member in channel_members:
        new_member = ChannelMember(channel_id=member['channel_id'], user_id=member['user_id'])
        db.session.add(new_member)
    db.session.commit()

def undo_channel_members():
    db.session.execute('TRUNCATE channelMembers RESTART IDENTITY CASCADE;')
    db.session.commit()

def undo_channels():
    db.session.execute('TRUNCATE channels RESTART IDENTITY CASCADE;')
    db.session.commit()

def seed_channel_messages():
    # i === channels
    for i in range(1, 10):
        channel = Channel.query.get(i)
        if channel.name == 'General':
            message = ChannelMessage(channel_id=i, sender_id=1, content=f'Welcome to {channel.server.name}\'s Server')
            db.session.add(message)
        else:
            message = ChannelMessage(channel_id=i, sender_id=1, content=f'Welcome to {channel.server.name}\'s Channel {channel.name}')
            db.session.add(message)
        #  x === users
        for x in range(2, 19):
                # users 2-3 channels 1-3
            if x < 9 and i < 4:
                message = ChannelMessage(channel_id=i, sender_id=x, content='test')
                db.session.add(message)
                # users 9 - 13 channels 4-6
            elif (x >= 9 and x < 14) and i <= 6 and i > 3:
                message = ChannelMessage(channel_id=i, sender_id=x, content='test')
                db.session.add(message)
                # users 13 - 18  channels 7-9
            elif (x > 13 and x < 19) and i <= 9 and i > 6:
                message = ChannelMessage(channel_id=i, sender_id=x, content='test')
                db.session.add(message)

        # message = ChannelMessage(channel_id=i, sender_id=18, content='test')
        # db.session.add(message)
    message_from_me = ChannelMessage(channel_id=10, sender_id=2, content="Hello, Thank you for visiting Diss-cord, an on going discord clone project, if you have any questions, feel free to message me here. If you'd like to know more about the project or myself feel free to click the github, or linked icons within the left navbar.")
    db.session.add(message_from_me)
    db.session.commit()

def undo_channel_messages():
    db.session.execute('TRUNCATE channelMessages RESTART IDENTITY CASCADE;')
    db.session.commit()