import streamlit as st
import os
from matplotlib import image
import pandas as pd
import plotly.express as px

with st.container():

    st.header('Module1 Working with :orange[IRIS DATASET]')

    iris_img_path = os.path.join('resources','iris_flowers.jpg')
    st.image(iris_img_path)

    iris_path=os.path.join('resources','iris.csv')
    df = pd.read_csv(iris_path)
    st.header(':red[Iris DataSet]')
    st.dataframe(df)

    st.subheader("Histogram of Sepalength v/s Count")
    species = st.selectbox("Select the Species",df['Species'].unique())

    fig1 = px.histogram(df[df['Species']==species],x='SepalLengthCm')
    st.plotly_chart(fig1,use_container_width=True)

    st.subheader(':red[Box plots of the selected Species]')

    fig2 = px.box(df[df['Species']==species],y='SepalLengthCm')
    st.plotly_chart(fig2,use_container_width=True)


import time

import displayio
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text.label import Label

class Clock:
    """
    Clock class

    - gets the current time via NTP
    - calculates the current time considering the timezone offset
    - displays the current time on the LED matrix
    """

    KEY = "clock"
    KEY_NTP = "ntp"
    KEY_TIMEZONE = "timezone"
    KEY_SOLAR = "solar"

    DEFAULT_NTP_REFRESH_INTERVAL = 60 * 60 * 6
    DEFAULT_COLOR = 0x00FF00

    def __init__(self, app):
        """
        :param app: the GiveMeASign object this belongs to
        :param ntp_socket_number: the socket number for use by the NTP client
        """
        self._app = app

        self._group = displayio.Group()

        font = bitmap_font.load_font("/assets/IBMPlexMono-Medium-24_jep.bdf")
        self._clock_label = Label(font)
        self._group.append(self._clock_label)

        self._last_ntp_check = None
        self._ntp_update()

        self._last_update_time = None

        self._timezone_breaks = None
        self._timezone_cache_until = 0
        self._timezone_cached_offset = 0

    def clock(self, label) -> None:
        """Put the clock into the given label"""
        label.color = self._calculate_color(time.time())
        now = time.localtime(self.get_local_time())

        colon = ":" if now[5] % 2 else " "

        label.text = f"{now[3]}{colon}{now[4]:02d}"

    def update_time(self):
        """Updates the display with the current time; blinks the colon once per second"""
        self.clock(self._clock_label)

        # returns [x, y, width, height]
        bb_width = self._clock_label.bounding_box[2]

        self._clock_label.x = round(self._app.display.width / 2 - bb_width / 2)
        self._clock_label.y = self._app.display.height // 2
        self._app.display.show(self._group)

    def mini_clock(self) -> Label:
        """Create and return a label with the current time rendered into it in a small font"""
        font = bitmap_font.load_font(
            "/assets/fonts/intelone-mono-font-family-regular-6.bdf"
        )
        #        font = bitmap_font.load_font("/assets/fonts/Segment7Standard.bdf")
        label = Label(font)

        self.clock(label)

        return label

    def loop(self):
        """
        Do loop processing:

        - call NTP if needed
        - update the display if needed (once per second)
        """
        if (
            self._last_ntp_check is None
            or time.time() > self._last_ntp_check + 60 * 60 * 3
        ):
            print("NTP update")
            self._ntp_update()
            self._last_ntp_check = time.time()

        # one clock update per second
        # something's wrong with this conditional, the clock is not updating
        if (
            self._last_update_time is None
            or time.monotonic_ns() > self._last_update_time + 1e9
        ):
            self._last_update_time = time.monotonic_ns()
            self.update_time()

        self.update_time()

    def get_local_time(self):
        """Returns the local time in seconds since Jan 1 1970, adjusted by the timezone offset"""
        now = time.time()
        self._check_timezone_offset()
        return now + self._timezone_cached_offset

    def _check_timezone_offset(self) -> None:
        """
        Gets the timezone offset for the current time.

        Caches the offset until the next transition.

        Timezone offsets are stored in Data under the key "timezone"

        They shoud be moved to Data with an endpoint to set them
        """
        now = time.time()

        if (
            self._timezone_cache_until != 0
            and now < self._timezone_cache_until
            or not self._app.data.has_item(Clock.KEY_TIMEZONE)
        ):
            return

        try:
            self._timezone_breaks = self._app.data.get_item(Clock.KEY_TIMEZONE)

            if len(self._timezone_breaks["transitions"]) == 0:
                return

            prev_time = 0
            self._timezone_cache_until = now + 1e12
            for transition in self._timezone_breaks["transitions"]:
                if (
                    transition["timestamp"] > now
                    and transition["timestamp"] < self._timezone_cache_until
                ):
                    self._timezone_cache_until = transition["timestamp"]

                if transition["timestamp"] > now or transition["timestamp"] < prev_time:
                    continue

                self._timezone_cached_offset = transition["offset"]

            self._app.logger.info(
                f"clock:_check_timezone_offset -> {self._timezone_cached_offset}"
            )
        except KeyError:
            self._app.logger.error("clock:_check_timezone_offset failed")

            self._timezone_breaks = None

    def _calculate_color(self, now):
        """
        Return different colors depending on the time's relationship to dawn or dusk.

        Depends on "solar" being set in Data
        """
        solar = self._app.data.get_item(Clock.KEY_SOLAR)
        if solar is None:
            return Clock.DEFAULT_COLOR

        try:
            if solar["sunset"] - 60 * 60 <= now <= solar["sunset"]:
                return 0xFFA500  # orange

            if solar["sunrise"] - 60 * 60 <= now <= solar["sunrise"]:
                return 0x0000FF  # blue

            if solar["sunset"] < solar["sunrise"] and now <= solar["sunset"]:
                return 0x00FF00  # green

            return 0xFF0000  # red
        except KeyError:
            self._app.logger.error("clock:_calculate_color failed")

            return Clock.DEFAULT_COLOR

    @property
    def timezone_offset(self) -> int:
        """Returns the current timezone offset - used outside of the class for debugging"""
        return self._timezone_cached_offset

    @property
    def is_sundown(self) -> bool:
        """
        Return True if the sun is currently down

        Depends on "solar" being set in Data
        """
        solar = self._app.data.get_item("solar")
        if solar is None:
            return None

        now = time.time()

        try:
            if solar["sunset"] - 30 * 60 <= now <= solar["sunset"]:
                return True

            if now <= solar["sunset"]:
                return False

            return True
        except KeyError:
            return False

    def _ntp_update(self) -> None:
        ntp_data = self._app.data.get_item(
            Clock.KEY_NTP,
            {
                "refresh_interval": Clock.DEFAULT_NTP_REFRESH_INTERVAL,
                "server": "pool.ntp.org",
            },
        )

        try:
            refresh_interval = ntp_data["refresh_interval"]
        except KeyError:
            refresh_interval = Clock.DEFAULT_NTP_REFRESH_INTERVAL

        if (
            self._last_ntp_check is not None
            and refresh_interval != 0
            and time.time() - self._last_ntp_check < refresh_interval
        ):
            return

        #        try:
        #            server = ntp_data["server"]
        #            ntp = NTP(self._app.esp, server)
        #        except KeyError:
        #            ntp = NTP(self._app.esp)

        updated_time = self._app.platform.ntp_sync()
        print(f"ntp_sync {updated_time}")
        if updated_time is not None:
            self._last_ntp_check = time.time()
            self._app.rtc.datetime = updated_time


from rest_framework.viewsets import ModelViewSet
from rest_framework import permissions
from inventory.models import (
						DebitNote,
						DebitNoteLine
					)

from inventory.serializers import (
						DebitNoteListSerializer,
						DebitNoteCreateSerializer,
						DebitNoteListSerializer,
						DebitNoteDetailSerializer,
						DebitNoteLineSerializer,
					)

class DebitNoteViewSet(ModelViewSet):
	queryset = DebitNote.objects.all()
	# permission_classes = [
 #        permissions.IsAuthenticated,
 #    ]

	def get_serializer_class(self):
		if self.action == 'list':
		    return DebitNoteListSerializer
		elif self.action == 'retrieve':
			return DebitNoteDetailSerializer
		return DebitNoteCreateSerializer


#!/usr/bin/env python3

import requests
import ST7735
import time
from bme280 import BME280
# from pms5003 import PMS5003, ReadTimeoutError
from subprocess import PIPE, Popen, check_output
from PIL import Image, ImageDraw, ImageFont
from fonts.ttf import RobotoMedium as UserFont

try:
    from smbus2 import SMBus
except ImportError:
    from smbus import SMBus

print("""luftdaten.py - Reads temperature, pressure, humidity,
PM2.5, and PM10 from Enviro plus and sends data to Luftdaten,
the citizen science air quality project.

Note: you'll need to register with Luftdaten at:
https://meine.luftdaten.info/ and enter your Raspberry Pi
serial number that's displayed on the Enviro plus LCD along
with the other details before the data appears on the
Luftdaten map.

Press Ctrl+C to exit!

""")

bus = SMBus(1)

# Create BME280 instance
bme280 = BME280(i2c_dev=bus)

# Create LCD instance
disp = ST7735.ST7735(
    port=0,
    cs=1,
    dc=9,
    backlight=12,
    rotation=270,
    spi_speed_hz=10000000
)

# Initialize display
disp.begin()

# Create PMS5003 instance
pms5003 = PMS5003()

# Read values from BME280 and PMS5003 and return as dict
def read_values():
    values = {}
    cpu_temp = get_cpu_temperature()
    raw_temp = bme280.get_temperature()
    comp_temp = raw_temp - ((cpu_temp - raw_temp) / comp_factor)
    values["temperature"] = "{:.2f}".format(comp_temp)
    values["pressure"] = "{:.2f}".format(bme280.get_pressure() * 100)
    values["humidity"] = "{:.2f}".format(bme280.get_humidity())
    try:
        pm_values = pms5003.read()
        values["P2"] = str(pm_values.pm_ug_per_m3(2.5))
        values["P1"] = str(pm_values.pm_ug_per_m3(10))
    except ReadTimeoutError:
        pms5003.reset()
        pm_values = pms5003.read()
        values["P2"] = str(pm_values.pm_ug_per_m3(2.5))
        values["P1"] = str(pm_values.pm_ug_per_m3(10))
    return values

# Get CPU temperature to use for compensation
def get_cpu_temperature():
    process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE, universal_newlines=True)
    output, _error = process.communicate()
    return float(output[output.index('=') + 1:output.rindex("'")])

# Get Raspberry Pi serial number to use as ID
def get_serial_number():
    with open('/proc/cpuinfo', 'r') as f:
        for line in f:
            if line[0:6] == 'Serial':
                return line.split(":")[1].strip()

# Check for Wi-Fi connection
def check_wifi():
    if check_output(['hostname', '-I']):
        return True
    else:
        return False

# Display Raspberry Pi serial and Wi-Fi status on LCD
def display_status():
    wifi_status = "connected" if check_wifi() else "disconnected"
    text_colour = (255, 255, 255)
    back_colour = (0, 170, 170) if check_wifi() else (85, 15, 15)
    id = get_serial_number()
    message = "{}\nWi-Fi: {}".format(id, wifi_status)
    img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
    draw = ImageDraw.Draw(img)
    size_x, size_y = draw.textsize(message, font)
    x = (WIDTH - size_x) / 2
    y = (HEIGHT / 2) - (size_y / 2)
    draw.rectangle((0, 0, 160, 80), back_colour)
    draw.text((x, y), message, font=font, fill=text_colour)
    disp.display(img)

def send_to_luftdaten(values, id):
    pm_values = dict(i for i in values.items() if i[0].startswith("P"))
    temp_values = dict(i for i in values.items() if not i[0].startswith("P"))

    # pm_values_json = [{"value_type": key, "value": val} for key, val in pm_values.items()]
    temp_values_json = [{"value_type": key, "value": val} for key, val in temp_values.items()]

    resp_1 = requests.post(
        "https://api.luftdaten.info/v1/push-sensor-data/",
        json={
            "software_version": "enviro-plus 0.0.1",
            "sensordatavalues": pm_values_json
        },
        headers={
            "X-PIN": "1",
            "X-Sensor": id,
            "Content-Type": "application/json",
            "cache-control": "no-cache"
        }
    )

    resp_1 = requests.post(
        "https://api.luftdaten.info/v1/push-sensor-data/",
        json={
            "software_version": "enviro-plus 0.0.1",
            "sensordatavalues": temp_values_json
        },
        headers={
            "X-PIN": "11",
            "X-Sensor": id,
            "Content-Type": "application/json",
            "cache-control": "no-cache"
        }
    )

    if resp_1.ok:
        return True
    else:
        return False

# Compensation factor for temperature
comp_factor = 2.25

# Raspberry Pi ID to send to Luftdaten
id = "raspi-" + get_serial_number()

# Width and height to calculate text position
WIDTH = disp.width
HEIGHT = disp.height

# Text settings
font_size = 16
font = ImageFont.truetype(UserFont, font_size)

# Display Raspberry Pi serial and Wi-Fi status
print("Raspberry Pi serial: {}".format(get_serial_number()))
print("Wi-Fi: {}\n".format("connected" if check_wifi() else "disconnected"))

time_since_update = 0
update_time = time.time()

# Main loop to read data, display, and send to Luftdaten
while True:
    try:
        time_since_update = time.time() - update_time
        values = read_values()
        print(values)
        if time_since_update > 145:
            resp = send_to_luftdaten(values, id)
            update_time = time.time()
            print("Response: {}\n".format("ok" if resp else "failed"))
        display_status()
    except Exception as e:
        print(e)


from Bio import SeqIO
import re
import sys
from collections import Counter
import argparse

parser = argparse.ArgumentParser(description='Building output scaffolding')
parser.add_argument('--scafolds', dest="scaffolds", type=str, required=True, help="fasta file with output scaffolds")
parser.add_argument('--contigs', dest="contigs", type=str, required=True, help="fasta file with contigs")
parser.add_argument('--outscaf', dest="outscaf", type=str, required=True, help="output scaf file (output scaffolding)")

args = parser.parse_args()

contigs = {}
for record in SeqIO.parse(args.contigs, "fasta"):
    contigs[str(record.seq).upper()] = record.id + ":::1"
    contigs[str(record.seq.reverse_complement()).upper()] = record.id + ":::-1"

a = Counter(contigs.values())

scaffolds = []
for scaffold in SeqIO.parse(args.scaffolds, "fasta"):
    scaffolds.append(scaffold.seq)

scafs = []
for scaffold in scaffolds:
    myscaf = []
    metacontigs = re.split("[N|n]+", str(scaffold))
    distances = iter(map(len, re.findall("[N|n]+", str(scaffold))) + [0])
    for jj, meta in enumerate(metacontigs):
        #if jj % 1000 == 0:
        #    print jj
        #print jj, "MMM"
        contig = contigs.get(meta, "NA")
        if contig == "NA":
            contained = False
            good = None
            for key in contigs.keys():
                if meta.upper() in key:
                    contained = True
                    good = contigs[key]
                    break
            if contained:
                contig = good + ":::" + str(len(meta)) + ":::" + str(distances.next())
                myscaf.append(contig)
            else:
                # scaffold consists of several contigs sticked together
                intervals = {}
                for key in contigs.keys():
                    position = meta.upper().find(key)
                    if position != -1:
                        intervals[contigs[key] + ":::" + str(len(key))] = (position, position + len(key))
                intervals = sorted(intervals.items(), key=lambda x: x[1][0])
                remove = set()
                for i in range(len(intervals)):
                    for j in range(len(intervals)):
                        if i == j:
                            continue
                        int1 = intervals[i][1]
                        int2 = intervals[j][1]
                        if int1[0] >= int2[0] and int1[1] <= int2[1]:
                            # interval int1 is containing in another one - skip it
                            remove.add(i)
                intervals2 = []
                for i in range(len(intervals)):
                    if i not in remove:
                        intervals2.append(intervals[i])
                mymyscaf = []
                for i in range(len(intervals2) - 1):
                    mymyscaf.append(intervals2[i][0] + ":::" + str(intervals2[i + 1][1][0] - intervals2[i][1][1]))
                mymyscaf.append(intervals2[-1][0] + ":::" + str(distances.next()))
                myscaf.extend(mymyscaf)
        else:
            contig = contig + ":::" + str(len(meta)) + ":::" + str(distances.next())
            myscaf.append(contig)
    scafs.append(myscaf)

with open(args.outscaf, "w") as f:
    for i, scaf in enumerate(scafs):
        f.write(">scaffold_%s\n" % i)
        for c in scaf:
            f.write("%s\n" % c)


import glob
txt_files = glob.glob("*.txt")

data = {}

def read_data(file):
    with open(file, encoding='utf-8') as f:
        result = f.read()
    return result

for file in txt_files:
    with open(file, encoding='utf-8') as f:
        line_count = 0
        for line in f:
            line_count += 1
    data[file] = {'count': line_count, 'read': read_data(file)}
sorted_data = sorted(data.items(), key=lambda x: x[1]['count'])
dic = dict(sorted_data)

for key, value in dic.items():
    result = f'{key} \n{dic[key]["count"]} \n{dic[key]["read"]}'
    print(result)


"""
Copy doge's nose and paste it on top left with OpenCV
"""

# Import Library
import cv2 as cv
import numpy as np
import os

# Get absolute path
# Reference: https://stackoverflow.com/questions/27844088/python-get-directory-two-levels-up
abs_path = os.path.dirname(os.path.dirname(__file__))
img_path = os.path.join(abs_path, 'input/image/doge.jpg')

# Read an image
img = cv.imread(img_path,cv.IMREAD_COLOR)

# Pickup the last pixel of nose
before_px = img[330,395]

# Pickup nose by reference (because nose is not a list)
nose = img[240:340,300:400]

# Draw some white
# Note: this white proved that nose is pick up by reference , not by value
img[320:360,360:400] = [255,255,255]

# Print nose's Region of Image (ROI)
print(nose)

# Pick up the last pixel of nose after whiten
after_px = img[330,395]

# Put nose at the top left corner
img[0:100,0:100] = nose

# Draw a rectangle on doge's nose with cv
cv.rectangle(img, (300,240),(400,340), (0,255,0),3)

# Put text label
cv.putText(img,'nose',(300,250),cv.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),1)

# Open Image in a window
cv.imshow('image',img)
# When wait for 0 millisecond, it will exit with any key pressed
cv.waitKey(0)
cv.destroyAllWindows()

# Print pixel to compare (still by reference)
# print(before_px)
# print(after_px)


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from geckoprocesstypes import process_types

def process_name(string_name):
    if string_name == "default":
        string_name = "main"
    if string_name == "tab":
        string_name = "content"
    return string_name

def gen_process_map():
    kIdentifier = "/* SUBST: CRASH_MANAGER_PROCESS_MAP */"
    crashManagerMap = """
  processTypes: {"""

    for p in process_types:
        crashManagerMap += """
    // A crash in the %(procname)s process.
    %(proctype)d: "%(procname)s",""" % {
            "proctype": p.enum_value,
            "procname": process_name(p.string_name),
        }
    crashManagerMap += """
  },"""

    return (kIdentifier, crashManagerMap)

def gen_process_pings():
    kIdentifier = "/* SUBST: CRASH_MANAGER_PROCESS_PINGS */"
    crashManagerPing = ""

    for p in process_types:
        crashManagerPing += """
      "%(proctype)s": %(crashping)s,""" % {
            "proctype": process_name(p.string_name),
            "crashping": "true" if p.crash_ping else "false",
        }

    return (kIdentifier, crashManagerPing)

def main(o, crashManager):
    subst = [gen_process_map(), gen_process_pings()]
    with open(crashManager, "r") as src:
        for l in src.readlines():
            for (id, value) in subst:
                if id in l:
                    l = l.replace(id, value)
            o.write(l)


#!/usr/bin/env python

from __future__ import print_function

import sys
import fontforge

def main(targetFile, *sources):
    target = fontforge.font()
    for sourceFile in sources:
        target.mergeFonts(sourceFile)

    target.generate(targetFile)

if __name__ == "__main__":
    main(*sys.argv[1:])


import numpy as np
import pandas as pd
import re

from recordclass import RecordClass
from typing import Any, Dict, List, NamedTuple, Optional, Set, Text

from state_data_mapper import nces_metadata_joiner_lib

class ColumnMapping(NamedTuple):
  """Defines how to process columns in state data source file."""
  # Processed output file column name.
  target_column: Text
  # Source file column name.
  source_column: Optional[Text] = None
  # Pandas data type (for casting and validation).
  dtype: Any = None
  # Converter function/lambda.
  converter: Any = None
  # Converter dictionary. If provided, will create a converter that maps values
  # according to this dictionary (if the key is present, otherwise keep the
  # original value).
  converter_dict: Dict[Any, Any] = None
  # Constant value for target column (if provided, source_column is ignored).
  constant: Any = None
  # Expected null values in source column.
  na_values: Optional[List] = None
  # Is temporary column. Will be use for intermediate manipulation, but will not
  # be in the final data frame.
  is_temporary: bool = False
  # Calculate this column from other columns.
  calculation: Any = None
  # List of values for rows that need to be filtered out.
  filter_values: List[Any] = None
  # Drop rows from the data frame if this column value is NA.
  dropna: bool = False

class StateConfig(NamedTuple):
  """Contains configuration for a state data source file."""
  # State name, e.g. "Colorado".
  state: Text
  # State abbreviation, e.g. "CO".
  state_abbreviation: Text
  # State data source XLSX filepath. Expects sheet named "Data for {state}".
  source_filepath: Text
  # Processed output CSV filepath.
  target_filepath: Text
  # List of column mapping from source file to target file.
  column_mappings: List[ColumnMapping] = []
  # Source sheet name containing data. If not specified, then read from
  # "Data for {state}".
  source_sheet_name: Optional[Text] = None
  # If more than one, source sheet name(s) containing data.
  # If not specified, then read from "Data for {state}".
  source_sheet_names_list: List[Text] = []
  # If True, then output rows are deduped.
  dedupe_rows: bool = True
  # Filter values file path. XLSX file whose rows with matching values will be
  # filtered out of the case data file.
  filter_values_file: Text = None
  # Filter value file columns to match on.
  filter_values_file_match_on: List[Text] = []
  # Filter value file columns to match on with fuzzy text matching.
  filter_values_file_fuzzy_match_on: List[Text] = []
  nces_id_lookup_file: Text = None
  nces_id_lookup_file_match_on: List[Text] = []
  nces_id_lookup_file_fuzzy_match_on: List[Text] = []

class ColumnReadReport(RecordClass):
  """Report summarizing the processed output column."""
  state: Text               # State name.
  column: Text              # Column name in the processed output.
  dtype: Any                # Pandas data type.
  count: int = None         # Number of non-null values.
  null_count: float = None  # Number of null values.
  min: Any = None           # Minimum.
  max: Any = None           # Maximum.
  mean: Any = None          # Mean (only defined for numeric columns).
  mode: Any = None          # Mode.

def converter_dict_getter(converter_dict: Dict[Any, Any]):
  """Returns a function that looks up a key in a dict or returns the key if
  the value is not found."""
  def get(x: Any):
    return converter_dict.get(x, x)
  return get

def coerce_int(value):
  coerced_numeric_value = pd.to_numeric(value, errors="coerce")
  if (pd.notna(coerced_numeric_value) and
      int(coerced_numeric_value) == coerced_numeric_value):
    return str(int(coerced_numeric_value))
  else:
    return value

def normalize(s: Text) -> Text:
  """Normalize a string for easier matching."""
  if not isinstance(s, str):
    return s
  tokens = list()
  for token in re.split('[^a-zA-Z0-9]', s.lower()):
    if token:
      tokens.append(token.strip())
  return " ".join(tokens)

def strip_and_clean_string(input: Text) -> Text:
  """Remove newlines and trailing spaces."""
  return " ".join(input.split())

def left_join(
    left_df: pd.DataFrame,
    right_df: pd.DataFrame,
    on: List[Text],
    on_fuzzy_match_columns: List[Text]):
  """Left join data frames on given columns. Handles string fuzzy match.

  Args:
    left_df: left data frame
    right_df: right data frame.
    on: list of columns to match on.
    on_fuzzy_match_columns: additional string columns to fuzzy match on.

  Returns:
    Left joined data frame.
  """
  assert set(on).issubset(left_df.columns)
  assert set(on).issubset(right_df.columns)
  assert not set(on_fuzzy_match_columns).issubset(on)
  left_df = left_df.copy(deep=True)
  right_df = right_df.copy(deep=True)
  normalized_columns = []
  # Create temporary string columns with normalized versions of the strings for
  # fuzzy matching.
  for column in on_fuzzy_match_columns:
    assert column in left_df.columns
    assert column in right_df.columns
    column_normalized = "_normalized_" + column
    normalized_columns.append(column_normalized)
    left_df[column_normalized] = left_df[column].transform(normalize)
    right_df[column_normalized] = right_df[column].transform(normalize)
    # Drop the original column from the right data frame (we don't need it
    # anymore now that the normalized version of it available.
    right_df = right_df.drop(column, axis=1)

  merged_df = left_df.merge(right_df, on=on + normalized_columns, how="left")
  # Drop the normalized columns from the merged dataframe.
  for column in normalized_columns:
    merged_df.drop(column, axis=1, inplace=True)
  return merged_df

def filter_matching_rows(
    left_df: pd.DataFrame,
    right_df: pd.DataFrame,
    on: List[Text],
    on_fuzzy_match_columns: List[Text],
    filter_out=True):
  """Filter matching rows from left data frame.

  Args:
    left_df: left data frame
    right_df: right data frame.
    on: list of columns to match on.
    on_fuzzy_match_columns: additional string columns to fuzzy match on.
    filter_out: If True, matching rows are filtered out. If False,
                non-matching rows are filtered out.

  Returns:
    Left data frame without matching rows from right data frame.
  """
  right_df = right_df[on + on_fuzzy_match_columns].copy(deep=True)
  right_df["_drop"] = True
  merged_df = left_join(left_df, right_df, on, on_fuzzy_match_columns)
  if filter_out:
    merged_df = merged_df[merged_df["_drop"].isna() |
                          (merged_df["_drop"] == False)]
  else:
    merged_df = merged_df[merged_df["_drop"] == True]
  merged_df.drop("_drop", axis=1, inplace=True)
  return merged_df

def process_fixed_length_codes(codes: Text, length: int) -> Text:
  """Ensures NCES codes are fixed length strings of numbers.

  If there is more than one code, then they should be comma-separated.
  """
  return ",".join([str(int(float(code.strip()))).zfill(length)
                   for code in codes.split(",")])

def process_state_data(
    state_config: StateConfig,
    required_columns: List[Text]=[],
    nces_school_metadata: Text=None,
    nces_district_metadata: Text=None
):
  """Read and process data for a single state based on config.

  Args:
    state_config: configuration for state data source.
    required_columns: List of mandatory output columns. If no data is available,
                      they will be empty in the output.
    nces_school_metadata: XLSX filepath containing NCESSchoolID, NCESDistrictID,
                          Charter, SchoolType columns.
    nces_district_metadata: XLSX filepath containing, NCESDistrictID, Charter,
                            DistrictType columns.

  Returns:
    (df, report_df) where df is the processed DataFrame and report_df is the
    DataFrame report summarizing the data.
  """

  # Process column mappings configuration.
  source_dtype_map = dict()
  target_dtype_map = dict()
  usecols = list()
  converters = dict()
  constant_columns = dict()
  column_rename_map = dict()
  na_values = dict()
  temporary_columns = list()
  for mapping in state_config.column_mappings:
    if mapping.is_temporary:
      temporary_columns.append(mapping.target_column)

    if mapping.constant:
      constant_columns[mapping.target_column] = mapping.constant
      assert not mapping.source_column, (
          f"For column {mapping.target_column} provide "
          "either constant or source column.")
      if mapping.dtype:
        target_dtype_map[mapping.target_column] = mapping.dtype
      continue
    if not mapping.source_column:
      continue

    # If this is a calculated column, then no need to read it from XLSX.
    if mapping.calculation:
      continue

    # Pandas XLSX read parameters
    usecols.append(mapping.source_column)
    column_rename_map[mapping.source_column] = mapping.target_column
    if mapping.converter_dict:
      converters[mapping.source_column] = converter_dict_getter(
          mapping.converter_dict)
    elif mapping.converter:
      converters[mapping.source_column] = mapping.converter
    elif mapping.dtype:
      source_dtype_map[mapping.source_column] = mapping.dtype
    if mapping.na_values:
      na_values[mapping.source_column] = mapping.na_values

  if state_config.source_sheet_names_list:
    df_list = []
    for sheet_name in state_config.source_sheet_names_list:
      # Read XLSX file.
      partial_df = pd.read_excel(
          state_config.source_filepath,
          # Sheet with this name must exist.
          sheet_name=sheet_name,
          usecols=usecols,  # Drop unmapped columns.
          dtype=source_dtype_map,  # Cast columns
          converters=converters,  # Drop unmapped columns.
          na_values=na_values  # Null values in source file.
      )
      df_list.append(partial_df)
    df = pd.concat(df_list)
  else:
    sheet_name = state_config.source_sheet_name
    if not sheet_name:
      sheet_name = f"Data for {state_config.state}"

    # Read XLSX file.
    df = pd.read_excel(
        state_config.source_filepath,
        # Sheet with this name must exist.
        sheet_name=sheet_name,
        usecols=usecols,  # Drop unmapped columns.
        dtype=source_dtype_map,  # Cast columns
        converters=converters,  # Drop unmapped columns.
        na_values=na_values  # Null values in source file.
    )

  # Rename columns.
  df.rename(columns=column_rename_map, errors="raise", inplace=True)

  # Constant columns.
  for column, value in constant_columns.items():
    df[column] = value
    if column in target_dtype_map:
      df[column] = df[column].astype(target_dtype_map[column])

  # Calculated columns.
  for mapping in state_config.column_mappings:
    if mapping.calculation:
      df[mapping.target_column] = df.apply(mapping.calculation, axis=1).astype(
          mapping.dtype)

  # Reorder columns in order of the config.
  df = df[[mapping.target_column for mapping in state_config.column_mappings]]

  # Validate dtypes.
  for mapping in state_config.column_mappings:
    if mapping.dtype:
      assert df[mapping.target_column].equals(
          df[mapping.target_column].astype(mapping.dtype)), (
          f"Invalid dtype '{mapping.dtype}' for "
          f"column '{mapping.target_column}' which has type "
          f"{df[mapping.target_column].dtype}.")

  # Remove rows that need to be filtered out from filter values in the config.
  for mapping in state_config.column_mappings:
    if mapping.filter_values:
      df = df[~df[mapping.target_column].isin(set(mapping.filter_values))]
    if mapping.dropna:
      df.dropna(subset=[mapping.target_column])

  # Remove rows that need to be filtered out based on the filter XLSX file.
  if state_config.filter_values_file:
    filter_values_df = pd.read_excel(state_config.filter_values_file)
    filter_columns = state_config.filter_values_file_match_on +\
                     state_config.filter_values_file_fuzzy_match_on
    assert filter_columns
    assert set(filter_columns).issubset(df.columns)
    assert set(filter_columns).issubset(filter_values_df.columns)
    df = filter_matching_rows(
        df,
        filter_values_df,
        state_config.filter_values_file_match_on,
        state_config.filter_values_file_fuzzy_match_on)

  # Dates should be mm/dd/YY.
  for mapping in state_config.column_mappings:
    if str(mapping.dtype).startswith("datetime64"):
      df[mapping.target_column] = df[mapping.target_column].dt.strftime(
          "%m/%d/%y")

  # Dedupe rows.
  if state_config.dedupe_rows:
    df.drop_duplicates(inplace=True)

  # Strip and clean up SchoolName, DistrictName, and City if present.
  for column in ["SchoolName", "DistrictName", "City"]:
    if column in df:
      df[column] = df[column].map(
          lambda value: strip_and_clean_string(value)
          if pd.notna(value) else value
      )

  # For integers in object type columns, cast as value as integer to avoid '.0'
  # suffix.
  for column in df:
    if not column.startswith("NCES") and df[column].dtype == object:
      df[column] = df[column].map(coerce_int)

  # Join NCES IDs
  if state_config.nces_id_lookup_file:
    nces_id_lookup_df = pd.read_excel(
        state_config.nces_id_lookup_file,
        dtype={
            "NCESSchoolID": pd.StringDtype(),
            "NCESDistrictID": pd.StringDtype(),
        })
    # Ensure that the NCES codes are strings.
    # if "NCESDistrictID" in nces_id_lookup_df:
    #   nces_id_lookup_df["NCESDistrictID"] =\
    #     nces_id_lookup_df["NCESDistrictID"].map(
    #       lambda value: process_fixed_length_codes(value, 7)
    #       if pd.notna((value)) else value
    #     )
    # if "NCESSchoolID" in nces_id_lookup_df:
    #   nces_id_lookup_df["NCESSchoolID"] = nces_id_lookup_df["NCESSchoolID"].map(
    #       lambda value: process_fixed_length_codes(value, 12)
    #       if pd.notna((value)) else value
    #   )
    filter_columns = state_config.nces_id_lookup_file_match_on + \
                     state_config.nces_id_lookup_file_fuzzy_match_on
    assert filter_columns
    assert set(filter_columns).issubset(df.columns)
    assert set(filter_columns).issubset(nces_id_lookup_df.columns)
    df = left_join(
        df,
        nces_id_lookup_df,
        state_config.nces_id_lookup_file_match_on,
        state_config.nces_id_lookup_file_fuzzy_match_on)

  # Join additional NCES metadata.
  # Either both nces_school_metadata and nces_district_metadata are available
  # or both are unavailable
  assert ((nces_school_metadata and nces_district_metadata) or (
      not nces_school_metadata and not nces_district_metadata))
  if nces_school_metadata and nces_district_metadata:
    nces_school_metadata_df = pd.read_excel(
        nces_school_metadata,
        usecols=["NCESSchoolID", "NCESDistrictID", "SchoolType", "Charter"],
        dtype=pd.StringDtype()
    )
    nces_district_metadata_df = pd.read_excel(
        nces_district_metadata,
        usecols=["NCESDistrictID", "DistrictType", "Charter"],
        dtype=pd.StringDtype()
    )
    if "NCESSchoolID" in df:
      assert "NCESDistrictID" in df
      df = nces_metadata_joiner_lib.join_nces_metadata_for_schools(
          df, nces_school_metadata_df, nces_district_metadata_df)
    elif "NCESDistrictID" in df:
      df = nces_metadata_joiner_lib.join_nces_metadata_for_districts(
          df, nces_district_metadata_df)

  # Drop temporary columns.
  df.drop(temporary_columns, axis=1, inplace=True)

  # Create report.
  report_rows = list()
  for column in df:
    column_report = ColumnReadReport(
        state_config.state,
        column,
        dtype=df[column].dtype,
        count=df[column].count(),
        null_count=df[column].isna().sum())
    column_report.column = column
    if df[column].dtype == object:
      column_report.min = df[column].astype("string").min()
      column_report.max = df[column].astype("string").max()
    else:
      column_report.min = df[column].min()
      column_report.max = df[column].max()
    mode = list(df[column].mode())
    column_report.mode = mode[0] if mode else np.NaN
    if pd.api.types.is_numeric_dtype(df[column]):
      column_report.mean = df[column].mean()
    report_rows.append(column_report)

  # Mandatory columns.
  for column in required_columns:
    if column not in df:
      df[column] = pd.Series(dtype="object")
      column_report = ColumnReadReport(
          state_config.state,
          column,
          dtype="object",
          count=df[column].count(),
          null_count=df[column].isna().sum())
      report_rows.append(column_report)

  # Reorder columns in the global column order.
  unexpected_columns = []
  if required_columns:
    for column in required_columns:
      assert(column in df.columns), column
    for column in df.columns:
      if column not in required_columns:
        print("Following column was unexpected:", column)
        unexpected_columns.append(column)
    df = df[required_columns + unexpected_columns]

  report_df = pd.DataFrame.from_records(
      report_rows,
      columns=["state", "column", "dtype", "count",
               "null_count", "min", "max", "mean", "mode"])

  # Write file.
  if state_config.target_filepath:
    df.to_excel(state_config.target_filepath, index=False)
    df.to_csv(state_config.target_filepath.replace(".xlsx", ".csv"),
              index=False)

  return df, report_df

def process_all_states(
    config: List[StateConfig],
    report_filepath: Text=None,
    required_columns: List[Text]=[],
    states_to_process: List[Text]=[],
    nces_school_metadata: Text=None,
    nces_district_metadata: Text=None
):
  """Process all states in list of configs.

  Args:
    config: List of StateConfigs defining how to process each file.
    report_filepath: If provided, then write the processed data summary
                     report to this path.
    required_columns: List of mandatory output columns. If no data is available,
                      they will be empty in the output.
    states_to_process: List of states to process from the config. If not
                       provided, then all states from the config will be
                       processed.
    nces_school_metadata: XLSX filepath containing NCESSchoolID, NCESDistrictID,
                          Charter, SchoolType columns.
    nces_district_metadata: XLSX filepath containing, NCESDistrictID, Charter,
                            DistrictType columns.

  Returns:
    (state_dfs, state_report_dfs): state_dfs is the list of processed state
    DataFrames and state_report_dfs is the list corresponding reports.
  """
  states_to_process = [state.lower() for state in states_to_process]
  state_dfs = list()
  state_report_dfs = list()
  for state_config in config:
    if states_to_process:
      if state_config.state.lower() not in states_to_process and \
          state_config.state_abbreviation.lower() not in states_to_process:
        continue
    print(f"Reading {state_config.state} from {state_config.source_filepath}.")
    df, report_df = process_state_data(
        state_config, required_columns, nces_school_metadata,
        nces_district_metadata)
    state_dfs.append(df)
    state_report_dfs.append(report_df)
    pd.set_option("display.max_columns", None, "display.width", 300)
  if report_filepath:
    print(f"Writing processed read reports to {report_filepath}...")
    pd.concat(state_report_dfs).to_csv(report_filepath, index=False)
  return state_dfs, state_report_dfs

def read_config_file(config_filepath: Text):
  """Read config file."""
  with open(config_filepath, "r") as f:
    contents = f.read()
    return eval(contents)


from django.shortcuts import render
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.http import JsonResponse
from .models import *
from django.db.models import Sum
# Create your views here.

def ErrorResponse(code, message):
    data = {}
    data['status'] = 'ERROR'
    data['code'] = code
    data['message'] = message
    return JsonResponse(data)

def SuccessResponse(like_num):
    data = {}
    data['status'] = 'SUCCESS'
    data['like_num'] = like_num or 0
    return JsonResponse(data)

def likeChange(request):
    user = request.user
    if not user.is_authenticated:
        return ErrorResponse(400, 'you were not login')

    content_type = request.GET.get('content_type')
    object_id = int(request.GET.get('object_id'))
    is_like = request.GET.get('is_like')

    content_type = ContentType.objects.get(model=content_type)

    # record = LikeRecord.objects.create(content_type=content_type, object_id=object_id, user=user)
    # counted, created = LikeCount.objects.get_or_create(content_type=content_type, object_id=object_id,user=user)

    if is_like == 'true':
        record, created = LikeRecord.objects.get_or_create(content_type=content_type, object_id=object_id, user=user)
        if created:
            print("created",record.like_num)
            record.like_num = 1
            record.save()
        else:
            pass
    else:
        record = LikeRecord.objects.get(content_type=content_type, object_id=object_id, user=user)
        print("exist()", record.like_num)
        record.delete()
        # record.save()
    # like_num = LikeRecord.objects.filter(content_type=content_type, object_id=object_id, user=user).count()%2
    like_counts = LikeRecord.objects.filter(object_id=object_id).aggregate(counts=Sum('like_num'))
    print('like_counts:',like_counts)
    return SuccessResponse(like_counts['counts'])


from __future__ import absolute_import, division, print_function
__metaclass__ = type

DOCUMENTATION = """
---
module: icx_firmware_upgrade
version_added: "1.3.0"
author: "Ruckus Wireless (@Commscope)"
short_description: Upgrades firmware of ICX switches
description:
  - This module copies new firmware to switch, flashes it to primary/secondary and reboots the switch.
notes:
  - Tested against ICX 10.1.
options:
  server_type:
    description:
      - Data transfer protocol to be used.
    type: str
    choices: ['scp', 'https', 'tftp']
  server_address:
    description:
      - IPV4/IPV6 address of the scp/https/tftp server.
    type: str
  server_port:
    description:
      - The port number of the server. Default values will be selected based on protocol type.
        Default scp:22, https:443
    type: int
  partition:
    description:
     - Partition to be used for upgrade.
    type: str
    required: true
    choices: ['primary','secondary','fips-ufi-primary-sig','fips-ufi-secondary-sig']
  scp_user:
    description:
      - remote username to be used for scp login.
    type: str
  scp_pass:
    description:
      - remote password to be used for scp login.
    type: str
  boot_only:
    description:
      - Boot the switch if True.
    default: no
    type: bool
    required: true
  save_running_config:
    description:
      - execute Write memory Command.
    default: no
    type: bool
  filename:
    description:
      - The path of the .bin/.sig file.
    type: str
"""

EXAMPLES = """
- name: upgrade firmware using scp
  community.network.icx_firmware_upgrade:
    server_type: scp
    server_address: 10.20.1.1
    partition: secondary
    filename: SPR08030.bin
    boot_only: false
    save_running_config: False
    scp_user: alethea
    scp_pass: alethea123
- name: upgrade firmware using tftp
  community.network.icx_firmware_upgrade:
    server_type: tftp
    server_address: 2001:db8::1
    partition: fips-ufi-primary-sig
    filename: signature_ufi.sig
    boot_only: False
    save_running_config: False
- name: upgrade firmware using https
  community.network.icx_firmware_upgrade:
    server_type: https
    server_address: 10.20.1.8
    partition: primary
    filename: SPR08030.bin
    boot_only: False
    save_running_config: False
- name: run only boot command
  community.network.icx_firmware_upgrade:
    boot_only: True
    save_running_config: True
"""

RETURN = """
changed:
  description: C(true) when file is copied and switch flashed with it. C(false) otherwise.
  returned: always
  type: bool
"""

from copy import deepcopy
import re

from ansible.module_utils._text import to_text
from ansible_collections.commscope.icx.plugins.module_utils.network.icx.icx import run_commands, exec_scp
from ansible.module_utils.basic import AnsibleModule, env_fallback
from ansible.module_utils.connection import ConnectionError
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.utils import remove_default_spec

def map_params_to_obj(module):
    commands = dict()
    command = ''
    res_commands = []
    server_type = module.params['server_type']
    server_address = module.params['server_address']
    server_port = module.params['server_port']
    filename = module.params['filename']
    partition = module.params['partition']
    if partition in ['fips-ufi-primary-sig', 'fips-ufi-secondary-sig']:
        boot_partition = partition.split('-')[2]
    else:
        boot_partition = partition
    boot_only = module.params['boot_only']
    save_running_config = module.params['save_running_config']
    if not boot_only:
        if server_type == 'tftp':
            command = 'copy tftp flash %s %s %s' % (server_address, filename, partition)
            commands['command'] = command

        elif server_type == 'scp':
            if server_port:
                command = 'copy scp flash %s %d %s %s' % (server_address, server_port, filename, partition)
            else:
                command = 'copy scp flash %s %s %s' % (server_address, filename, partition)
            commands['command'] = command
            commands['scp_user'] = module.params['scp_user']
            commands['scp_pass'] = module.params['scp_pass']

        elif server_type == 'https':
            if server_port:
                command = 'copy https flash %s %s %s port %d' % (server_address, filename, partition, server_port)
            else:
                command = 'copy https flash %s %s %s' % (server_address, filename, partition)

            commands['command'] = command
        res_commands.append(commands)
        if save_running_config:
            res_commands.append('write memory')
            res_commands.append('boot system flash %s yes' % (boot_partition))
        else:
            res_commands.append('boot system flash %s yes' % (boot_partition))
    else:
        if save_running_config:
            res_commands.append('write memory')
            res_commands.append('boot system flash %s yes' % (boot_partition))
        else:
            res_commands.append('boot system flash %s yes' % (boot_partition))

    return res_commands

def checkValidations(module):
    server_type = module.params['server_type']
    server_address = module.params['server_address']
    # server_port = module.params['server_port']
    filename = module.params['filename']
    boot_only = module.params['boot_only']
    scp_user = module.params['scp_user']
    scp_pass = module.params['scp_pass']

    if not boot_only:
        if server_type is None:
            module.fail_json(msg="server_type is required")
        if server_address is None:
            module.fail_json(msg="server_address is required")
        if filename is None:
            module.fail_json(msg="filename is required")
        if server_type == 'scp':
            if scp_user is None:
                module.fail_json(msg="scp_user is required")
            if scp_pass is None:
                module.fail_json(msg="scp_pass is required")

def main():
    """ main entry point for module execution
    """
    argument_spec = dict(
        server_type=dict(type='str', choices=['scp', 'https', 'tftp'], required=False),
        server_address=dict(type='str', required=False),
        server_port=dict(type='int'),
        partition=dict(type='str', choices=['primary', 'secondary', 'fips-ufi-primary-sig',
                                            'fips-ufi-secondary-sig'], required=True),
        filename=dict(type='str', required=False),
        boot_only=dict(type='bool', required=True),
        save_running_config=dict(type='bool'),
        scp_user=dict(type='str', required=False),
        scp_pass=dict(type='str', required=False, no_log=True),
    )

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)
    checkValidations(module)
    result = {'changed': False}

    commands = map_params_to_obj(module)

    if module.params['save_running_config']:
        if module.params['boot_only']:
            result['commands'] = [commands[0], commands[1]]
        else:
            result['commands'] = [commands[0]['command'], commands[1], commands[2]]
    else:
        if module.params['boot_only']:
            result['commands'] = [commands[0]]
        else:
            result['commands'] = [commands[0]['command'], commands[1]]

    if commands:
        if not module.check_mode:
            if module.params['server_type'] == 'scp':
                responses = exec_scp(module, commands[0])
                responses = run_commands(module, commands[1:])
            else:
                responses = run_commands(module, commands)
        result['changed'] = True
        result['responses'] = responses

    module.exit_json(**result)

if __name__ == '__main__':
    main()


import torch
from torch.autograd import Variable
import torch.nn.functional as F

x_data = Variable(torch.Tensor([[1.0], [2.0], [3.0]]))
y_data = Variable(torch.Tensor([[2.0], [4.0], [6.0]]))

class Model(torch.nn.Module):
	#initialize parameters model --> linear and one input and one output
	#forward function --> predict based on linear
    def __init__(self):

        super(Model, self).__init__()
        self.linear = torch.nn.Linear(1, 1)  # One in and one out

    def forward(self, x):
        y_pred = F.sigmoid(self.linear(x))
        return y_pred

#initlize model
model = Model()

#Mean Square loss
criterion = torch.nn.BCELoss(size_average=False)
#here SGD stands for Standard gradient descent  default params and learning rate
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

#training epochs
for epoch in range(500):
    #this is like a forward pass
    y_pred = model(x_data)

    #calculate loss on predicted and actual
    loss = criterion(y_pred, y_data)
    print(epoch, loss.data[0])
    #so till now we have got the loss from the variable graph now we need to back prop and update
    #initlize
    optimizer.zero_grad()
    #back prop the loss since loss is alredy a variable
    loss.backward()
    #Update the weightss
    optimizer.step()

hour_var = Variable(torch.Tensor([[1.0]]))
print("predict 1 hour ", 1.0, model(hour_var).data[0][0] > 0.5)
hour_var = Variable(torch.Tensor([[7.0]]))
print("predict 7 hours", 7.0, model(hour_var).data[0][0] > 0.5)


from collections import deque
N, X = map(int, input().split())
S = input()

que = deque([-1])
for s in S:
    if (que[-1] == 'L' or que[-1] == 'R') and s == 'U':
        que.pop()
    else:
        que.append(s)
que.popleft()

for q in que:
    if q == 'U':
        X = X // 2
    if q == 'L':
        X = X * 2
    if q == 'R':
        X = X * 2 + 1
print(X)


import monai
import numpy as np
from typing import Any, Callable, Optional, Tuple, Union, Mapping, Hashable, List, Sequence
from torch.utils.data._utils.collate import default_collate

# This module contains all the extra components needed for data loading and segmentation model training,
# some of which need to exist in any environment where the saved model is to be deployed.

# Custom transform to convert a collection of segmentation mask arrays to a single one-hot encoded array
class MasksToOneHotD(monai.transforms.MapTransform):
    def __init__(self, keys: monai.config.KeysCollection,
                 keyList: List[Hashable], newKeyName: str) -> None:
        super().__init__(keys)
        self.keyList = keyList
        self.newKeyName = newKeyName
        assert(len(keyList)>0)

    def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Mapping[Hashable, np.ndarray]:

        # (if this were to be contributed, I'd have to pay attention to whether keys are in data)
        # (also I'd want to raise more clear exceptions than these asserts)

        assert(all(key in self.keys for key in self.keyList))
        assert(all(key in data.keys() for key in self.keyList))
        assert(self.newKeyName not in data.keys())

        background_mask = (sum(data[key] for key in self.keyList)==0).astype('int8')

        # Assumes these were numpy arrays.
        # If they were torch tensors we'd have to do "torch.stack" and use argument "dim" instead of "axis"
        data[self.newKeyName] = np.stack(
            [background_mask] + [data[key] for key in self.keyList],
            axis=0
        )

        return data

# Custom transform to convert a collection of segmentation mask arrays to a single mask, one-hot encoded (e.g. union left and right lung into one thing)
# Always allows missing keys, just being a no-op if any keys are missing
class UnionMasksD(monai.transforms.MapTransform):
    def __init__(self, keys: monai.config.KeysCollection,
                 keyList: List[Hashable], newKeyName: str) -> None:
        super().__init__(keys)
        self.keyList = keyList
        self.newKeyName = newKeyName
        assert(len(keyList)>0)

    def __call__(self, data: Mapping[Hashable, np.ndarray]) -> Mapping[Hashable, np.ndarray]:

        if not all(key in data.keys() for key in self.keyList):
            return data

        assert(all(key in self.keys for key in self.keyList))
        assert(self.newKeyName not in data.keys())

        sum_of_masks = sum(data[key] for key in self.keyList)
        background_mask = (sum_of_masks==0).astype('int8')
        foreground_mask = (sum_of_masks!=0).astype('int8')

        # Assumes these were numpy arrays.
        # If they were torch tensors we'd have to do "torch.stack" and use argument "dim" instead of "axis"
        data[self.newKeyName] = np.stack(
            [background_mask, foreground_mask],
            axis=0
        )

        return data

def rgb_to_grayscale(x):
    """Given a numpy array with shape (H,W,C), return "grayscale" one of shape (H,W);
    behaves as no-op if given array with shape already being (H,W)"""
    if len(x.shape)==2: return x
    elif len(x.shape)==3: return x.mean(axis=2)
    else: raise Exception("rgb_to_grayscale: unexpected number of axes in array")

# Define a custom transform that drops out blob shapes of random values sampled from the image value

def blobbed(img, R):
    """Add a random metaball blob to an image, using the random state R"""
    img_max = img.max()
    val = R.uniform(max(img.min(),img_max/2),img_max)
    number_of_metaballs = R.randint(10,11)

    metaball_radius_mean = img.shape[2]/16
    metaball_radius_std = img.shape[2]/32

    metaball_radii = R.normal(metaball_radius_mean, scale = metaball_radius_std, size = number_of_metaballs)

    blob_center_y = R.uniform(0,img.shape[1])
    blob_center_x = R.uniform(0,img.shape[2])
    blob_std_y = img.shape[2]/8
    blob_std_x = img.shape[1]/8

    metaball_y_locations = R.normal(blob_center_y, scale = blob_std_y, size = number_of_metaballs)
    metaball_x_locations = R.normal(blob_center_x, scale = blob_std_x, size = number_of_metaballs)

    y, x = np.ogrid[tuple(slice(0, i) for i in img.shape[1:])]
    mask = sum(
        r**2 / ((y-y_loc)**2 + (x-x_loc)**2)
        for r, y_loc, x_loc in zip(metaball_radii, metaball_y_locations, metaball_x_locations)
    ) > 1
    img[0][mask]=val

    return img

class RandBlobDropoutD(monai.transforms.RandomizableTransform, monai.transforms.MapTransform):
    """
    Bleh.
    """

    backend = [monai.utils.enums.TransformBackends.NUMPY]

    def __init__(
        self,
        keys: monai.config.KeysCollection,
        prob: float = 0.1,
        allow_missing_keys: bool = False,
    ):
        monai.transforms.MapTransform.__init__(self, keys, allow_missing_keys)
        monai.transforms.RandomizableTransform.__init__(self, prob=prob)

    def __call__(self, data):
        d = dict(data)
        self.randomize(None)
        if not self._do_transform:
            return d

        for key in self.key_iterator(d):
            d[key] = blobbed(d[key], self.R)

        return d

# A custom version of list_data_collate copied straight out of MONAI codebase and slightly modified.
def list_data_collate_no_meta(batch: Sequence):
    """
    Enhancement for PyTorch DataLoader default collate.
    If dataset already returns a list of batch data that generated in transforms, need to merge all data to 1 list.
    Then it's same as the default collate behavior.

    Note:
        Need to use this collate if apply some transforms that can generate batch data.

    """
    elem = batch[0]
    data = [i for k in batch for i in k] if isinstance(elem, list) else batch
    key = None
    try:
        elem = batch[0]
        if isinstance(elem, Mapping):
            ret = {}
            for k in elem:
                key = k

                # Ebrahim's modification: skip any meta_dicts. Collating them is glitchy in my use-case.
                if "_meta_dict" in key: continue

                ret[k] = default_collate([d[k] for d in data])
            return ret
        return default_collate(data)
    except RuntimeError as re:
        re_str = str(re)
        if "equal size" in re_str:
            if key is not None:
                re_str += f"\nCollate error on the key '{key}' of dictionary data."
            re_str += (
                "\n\nMONAI hint: if your transforms intentionally create images of different shapes, creating your "
                + "`DataLoader` with `collate_fn=pad_list_data_collate` might solve this problem (check its "
                + "documentation)."
            )
        raise RuntimeError(re_str) from re
    # except TypeError as re:
    #     re_str = str(re)
    #     if "numpy" in re_str and "Tensor" in re_str:
    #         if key is not None:
    #             re_str += f"\nCollate error on the key '{key}' of dictionary data."
    #         re_str += (
    #             "\n\nMONAI hint: if your transforms intentionally create mixtures of torch Tensor and numpy ndarray, "
    #             + "creating your `DataLoader` with `collate_fn=pad_list_data_collate` might solve this problem "
    #             + "(check its documentation)."
    #         )
    #     raise TypeError(re_str) from re


# importing section
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy as sp
# using the Csv file
df = pd.read_csv('output.csv')

# Checking the first 5 entries of dataset
df.head()
# using the Csv file
df = pd.read_csv('output.csv')

# Checking the first 5 entries of dataset
df.head()
headers = ["symboling", "normalized-losses", "make",
		"fuel-type", "aspiration","num-of-doors",
		"body-style","drive-wheels", "engine-location",
		"wheel-base","length", "width","height", "curb-weight",
		"engine-type","num-of-cylinders", "engine-size",
		"fuel-system","bore","stroke", "compression-ratio",
		"horsepower", "peak-rpm","city-mpg","highway-mpg","price"]

df.columns=headers
df.head()
data = df

# Finding the missing values
data.isna().any()

# Finding if missing values
data.isnull().any()
# converting mpg to L / 100km
data['city-mpg'] = 235 / df['city-mpg']
data.rename(columns = {'city_mpg': "city-L / 100km"}, inplace = True)

print(data.columns)

# checking the data type of each column
data.dtypes
data.price.unique()

# Here it contains '?', so we Drop it
data = data[data.price != '?']

# checking it again
data.dtypes
data['length'] = data['length']/data['length'].max()
data['width'] = data['width']/data['width'].max()
data['height'] = data['height']/data['height'].max()

# binning- grouping values
bins = np.linspace(min(data['price']), max(data['price']), 4)
group_names = ['Low', 'Medium', 'High']
data['price-binned'] = pd.cut(data['price'], bins,
							labels = group_names,
							include_lowest = True)

print(data['price-binned'])
plt.hist(data['price-binned'])
plt.show()
# categorical to numerical variables
pd.get_dummies(data['fuel-type']).head()

# descriptive analysis
# NaN are skipped
data.describe()
# examples of box plot
plt.boxplot(data['price'])

# by using seaborn
sns.boxplot(x ='drive-wheels', y ='price', data = data)

# Predicting price based on engine size
# Known on x and predictable on y
plt.scatter(data['engine-size'], data['price'])
plt.title('Scatterplot of Enginesize vs Price')
plt.xlabel('Engine size')
plt.ylabel('Price')
plt.grid()
plt.show()
# Grouping Data
test = data[['drive-wheels', 'body-style', 'price']]
data_grp = test.groupby(['drive-wheels', 'body-style'],
						as_index = False).mean()

data_grp
# pivot method
data_pivot = data_grp.pivot(index = 'drive-wheels',
							columns = 'body-style')
data_pivot

# heatmap for visualizing data
plt.pcolor(data_pivot, cmap ='RdBu')
plt.colorbar()
plt.show()
# Analysis of Variance- ANOVA
# returns f-test and p-value
# f-test = variance between sample group means divided by
# variation within sample group
# p-value = confidence degree
data_annova = data[['make', 'price']]
grouped_annova = data_annova.groupby(['make'])
annova_results_l = sp.stats.f_oneway(
							grouped_annova.get_group('honda')['price'],
							grouped_annova.get_group('subaru')['price']
									)
print(annova_results_l)

# strong corealtion between a categorical variable
# if annova test gives large f-test and small p-value

# Correlation- measures dependency, not causation
sns.regplot(x ='engine-size', y ='price', data = data)
plt.ylim(0, )


'''
The Roll-over optimization problem from MIT lecture:
https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0002-
introduction-to-computational-thinking-and-data-science-fall-2016/lecture-slides
-and-files/MIT6_0002F16_lec2.pdf

Problem:
Score = (60	– (a+b+c+d+e))*F + a*ps1 + b*ps2 + c*ps3 + d*ps4 + e*ps5
Given F, ps1, ps2, ps3, ps4, ps5
Find a, b, c, d, e that maximize score
Where
a, b, c, d, e = 0 or 10
a+b+c+d+e >= 20

Solution:
Notice that
Score = 60*F + a*(ps1-F) + b*(ps2-F) + c*(ps3-F) + d*(ps4-F) + e*(ps5-F)
So we have to maximize part
max_score = a*(ps1-F) + b*(ps2-F) + c*(ps3-F) + d*(ps4-F) + e*(ps5-F)
'''

# ps and f - table with given ps1, ps2... and given f
# sum_ae - sum of a, b, c, d, e
# memo - dictionary with already calculated solutions for specific conditions
def max_score(ps, f, sum_ae=0, memo={}):
	# Checking if solution for specific conditions is saved in dictionary memo
	# Refering to solution by length of table ps and sum of variables a,...,e
	if (len(ps), sum_ae) in memo:
		result = memo[(len(ps), sum_ae)]

	# If table ps is empty, the solution is 0, sum_ae doesn't change
	elif ps==[]:
		result = (0, sum_ae)

	# if length of ps is 2 or 1 and sum_ae is 0 or 10,
	# then the value ps[i]-f has to be taken,
	# that means d and/or e has to have value 10
	elif (len(ps) == 2 and sum_ae == 0) or (len(ps) == 1 and sum_ae == 10):
		take, sum_ae = max_score(ps[1:], f, sum_ae+10, memo)
		take += 10 * (ps[0] - f)
		result = (take, sum_ae)

	# otherwise looking for optimal solution
	else:
		# checking the score while taking ps[i]-f,  a,b,c,d,e = 10
		take, sum_take = max_score(ps[1:], f, sum_ae+10, memo)
		take += 10 * (ps[0] - f)

		# checking the score while skiping ps[i]-f,  a,b,c,d,e = 0
		skip, sum_skip = max_score(ps[1:], f, sum_ae, memo)

		# checking what gives higher score
		if take > skip:
			result = (take, sum_take)
			sum_ae = sum_take
		else:
			result = (skip, sum_skip)
			sum_ae = sum_skip

	# saving the score to memo
	if (len(ps), sum_ae) not in memo:
		memo[(len(ps), sum_ae)] = result

	return result

# given values
f = 3
ps = [1, 2, 3, 4, 5]

# calculating max_score and final answer - score
s = max_score(ps, f)
score = 60 * f + s[0]

# printing solution
print('\nMaximal score: ', score)
print('a + b + c + d + e = ', s[1])
print()


#...................Explaination of Representations.................
'''
     The Sudoku Board:

  \ R  0  1  2    3  4  5    6  7  8
 C \
       bSquare6:  bSquare7:  bSquare8:
 8     72 73 74   75 76 77   78 79 80
 7     63 64 65   66 67 68   69 70 71
 6     54 55 56   57 58 59   60 61 62
       bSquare3:  bSquare4:  bSquare5:
 5     45 46 47   48 49 50   51 52 53
 4     36 37 38   39 40 41   42 43 44
 3     27 28 29   30 31 32   33 34 35
       bSquare0:  bSquare1:  bSquare2:
 2     18 19 20   21 22 23   24 25 26
 1     9  10 11   12 13 14   15 16 17
 0     0  1  2    3  4  5    6  7  8

 R = row
 C = column
 bSquare = big square
 square = individual little square (from 0 until 80 inclusive)
'''
import json
import datetime
from fractions import Fraction
from decimal import Decimal, getcontext
getcontext().prec = 40

#..........................User interface..................

def hardestSudokuInTheWorld():
    board = [0]*81
    board[72] = 8
    board[65] = 3
    board[66] = 6
    board[55] = 7
    board[58] = 9
    board[60] = 2
    board[46] = 5
    board[50] = 7
    board[40] = 4
    board[41] = 5
    board[42] = 7
    board[30] = 1
    board[34] = 3
    board[20] = 1
    board[25] = 6
    board[26] = 8
    board[11] = 8
    board[12] = 5
    board[16] = 1
    board[1] = 9
    board[6] = 4
    return board
def inputToBoard(board, boardIsEmpty):
    if boardIsEmpty:
        if input("Do you want to use the hardest board in the world?(y/n): ") == "y": board = hardestSudokuInTheWorld()
    lastSquareNumber = -1
    while True:
        print("\n\n\n\n\n\n\n\n\n\n")
        print("representation of the squares in the sudoku board:")
        printRepresentationOfPlaces()
        print("\n\nThis is how the board looks like in the meantime:")
        printBoard(board)
        print("")
        squareNumber = 0
        squareNumber = lastSquareNumber + 1
        if squareNumber == 81: squareNumber = 0
        correctInput = False
        valueToInput = 0
        while not(correctInput):
            correctInput = True
            try:
                valueToInput = int(input("What value do you want to input in square number " + str(squareNumber) + \
                                         "?\n(from 0 until 9 inclusive, or -1 for inputting somewhere else, or -2 for solve board): "))
            except ValueError:
                print("invalid input, not an integer")
                correctInput = False
                continue
            if valueToInput == -2:
                print("\nUsing this board:")
                printBoard(board)
                print("")
                return board
            elif valueToInput == -1:
                print("")
                correctInput1 = False
                while not(correctInput1):
                    correctInput1 = True
                    try:
                        squareNumber = int(input("What square number do you want to input to?\n(from 0 until 80 inclusive, or -1 or -2 for solve board): "))
                    except ValueError:
                        print("wrong input, not an integer")
                        correctInput1 = False
                        continue
                    if (squareNumber == -1) or (squareNumber == -2):
                        print("\nUsing this board:")
                        printBoard(board)
                        print("")
                        return board
                    if not((squareNumber >= 0) and (squareNumber <= 80)):
                        correctInput1 = False
                        print("wrong input, outside of range")
                    else:
                        print("")
                correctInput = False
            elif not((valueToInput >= 0) and (valueToInput <= 9)):
                correctInput = False
                print("invalid input, outside of range")
            else:
                boardC = board.copy()
                boardC[squareNumber] = valueToInput
                if not(isBoardValidBasedOnChangedSquare(boardC, squareNumber)):
                    if input("input is contradictory with existing board, are you sure it's correct?(y/n): ") == "n":
                        print("\nOk then, not using your last input")
                        correctInput = False
                    else: print("")
        lastSquareNumber = squareNumber
        board[squareNumber] = valueToInput
def createBoard():
    notFound = False
    try:
        lastBoard = open("lastBoardInputted.json")
        board = json.load(lastBoard)
        lastBoard.close()
    except FileNotFoundError:
        print("lastBoardInputted.json Not found! No worries. Making new board that you\'ll input to.")
        notFound = True
    if (notFound) or (input("Do you want to use your board from last time?(y/n): ") == "n"):
        board = [0]*81
        board = inputToBoard(board.copy(), True)
        lastBoard = open("lastBoardInputted.json", "w")
        json.dump(board, lastBoard)
        lastBoard.close()
        return board
    else:
        board = inputToBoard(board.copy(), False)
        lastBoard = open("lastBoardInputted.json", "w")
        json.dump(board, lastBoard)
        lastBoard.close()
        return board
def printBoard(board):
    print(createStringOfBoard(board))
def createStringOfBoard(board):
    strOfBoard = ""
    for row in range(8, -1, -1):
        for column in range(9):
            square = fromRowAndColumnToSquare(row, column)
            strOfBoard += str(board[square])
            if column == 8:
                if row != 0:
                    strOfBoard += "\n"
                if (row == 6) or (row == 3): strOfBoard += "\n"
            else:
                strOfBoard += " "
                if column == 2: strOfBoard += "  "
                elif column == 5: strOfBoard += "  "
    return strOfBoard
def printRepresentationOfPlaces():
    print("72 73 74   75 76 77   78 79 80\n63 64 65   66 67 68   69 70 71\n54 55 56   57 58 59   60 61 62\n\n45 46 47   48 49 50   51 52 53\n36 37 38   39 40 41   42 43 44\n27 28 29   30 31 32   33 34 35\n\n18 19 20   21 22 23   24 25 26\n9  10 11   12 13 14   15 16 17\n0  1  2    3  4  5    6  7  8 ")

#..................Functions For Actual Algorithm...............

def fromSquareToRow(square):
    return (square // 9)
def fromSquareToColumn(square):
    return (square % 9)
def fromSquareTobSquare(square):
    return ((square//27)*3 + (square%9)//3)
def fromRowAndColumnToSquare(row, column):
    return ((row*9) + column)
def bottomLeftSquareOfbSquare(bSquare):
    return ((bSquare//3)*27 + 3*(bSquare%3))
def frombSquareToSquares(bSquare):
    listOfSquares = [0]*9
    bottomLeftSquare = bottomLeftSquareOfbSquare(bSquare)
    counter = 0
    for skipUp in range(3):
        for skipRight in range(3):
            square = bottomLeftSquare + skipUp*9 + skipRight
            listOfSquares[counter] = square
            counter += 1
    return listOfSquares
def fromRowToSquares(row):
    listOfSquares = [0]*9
    leftSquare = fromRowAndColumnToSquare(row, 0)
    leftSquarePlus9 = leftSquare + 9
    counter = 0
    for square in range(leftSquare, leftSquarePlus9):
        listOfSquares[counter] = square
        counter += 1
    return listOfSquares
def fromColumnToSquares(column):
    listOfSquares = [0]*9
    bottomSquare = fromRowAndColumnToSquare(0, column)
    bottomSquarePlus73 = bottomSquare + 73
    counter = 0
    for square in range(bottomSquare, bottomSquarePlus73, 9):
        listOfSquares[counter] = square
        counter += 1
    return listOfSquares
def fromRowTobSquares(rowNum):
    listOfbSquares = [0]*3
    rnd3t3 = (rowNum//3)*3
    listOfbSquares[0] = rnd3t3
    rnd3t3 += 1
    listOfbSquares[1] = rnd3t3
    rnd3t3 += 1
    listOfbSquares[2] = rnd3t3
    return listOfbSquares
def isRowValid(board, rowNum):
    numbersTaken = [False]*10
    squaresOfRow = fromRowToSquares(rowNum)
    for square in squaresOfRow:
        value = board[square]
        if value == 0: continue
        if numbersTaken[value]: return False
        numbersTaken[value] = True
    return True
def isbSquareValid(board, bSquareNum):
    numbersTaken = [False]*10
    squaresOfbSquare = frombSquareToSquares(bSquareNum)
    for square in squaresOfbSquare:
        value = board[square]
        if value == 0: continue
        if numbersTaken[value]: return False
        numbersTaken[value] = True
    return True
def isColumnValid(board, columnNum):
    numbersTaken = [False]*10
    squaresOfColumn = fromColumnToSquares(columnNum)
    for square in squaresOfColumn:
        value = board[square]
        if value == 0: continue
        if numbersTaken[value]: return False
        numbersTaken[value] = True
    return True
def isBoardValidBasedOnChangedSquare(board, changedSquareNum):
    if not(isRowValid(board, fromSquareToRow(changedSquareNum))): return False
    if not(isColumnValid(board, fromSquareToColumn(changedSquareNum))): return False
    if not(isbSquareValid(board, fromSquareTobSquare(changedSquareNum))): return False
    return True
def isBoardValidBasedOnChangedRow(board, changedRowNum):
    for column in range(9):
        if not(isColumnValid(board, column)): return False
    listOfbSquares = fromRowTobSquares(changedRowNum)
    for bSquareNum in listOfbSquares:
        if not(isbSquareValid(board, bSquareNum)): return False
    return True
def listAllValidValuesForEachSquare(board):
    listOfValidValuesForEachSquare = [[] for _ in range(81)]
    boardC = board.copy()
    for square in range(81):
        bs = board[square]
        if bs != 0:
            listOfValidValuesForEachSquare[square].append(bs)
            continue
        for value in range(1, 10):
            boardC[square] = value
            if isBoardValidBasedOnChangedSquare(boardC, square): listOfValidValuesForEachSquare[square].append(value)
        boardC[square] = 0
    return listOfValidValuesForEachSquare
def listAllValidCombForRow(board, row, listOfValidValuesForEachSquare, squareNumsInRow):
    listOfAllValidCombForRow = []
    amountOfPossValuesForEachSquareInRow = [0]*9
    numSquare1To9 = 0
    for squareNum in squareNumsInRow:
        amountOfPossValuesForEachSquareInRow[numSquare1To9] = len(listOfValidValuesForEachSquare[squareNum])
        numSquare1To9 += 1
    currentNumPossForEachSquare = [0]*9
    currentSquareToChange = 0
    valuesUsed = [False]*10
    valuesUsedByStep = []
    while True: #replacement for a recursive algorithm
        possibilityNumber = currentNumPossForEachSquare[currentSquareToChange]
        if possibilityNumber >= amountOfPossValuesForEachSquareInRow[currentSquareToChange]:
            if currentSquareToChange == 0: break
            valuesUsed[valuesUsedByStep.pop()] = False
            currentNumPossForEachSquare[currentSquareToChange] = 0
            currentSquareToChange -= 1
            currentNumPossForEachSquare[currentSquareToChange] += 1
        else:
            currentValue = listOfValidValuesForEachSquare[squareNumsInRow[currentSquareToChange]][possibilityNumber]
            if valuesUsed[currentValue]: currentNumPossForEachSquare[currentSquareToChange] += 1
            else:
                if currentSquareToChange == 8:
                    valuesUsedByStep.append(currentValue)
                    listOfAllValidCombForRow.append(valuesUsedByStep.copy())
                    valuesUsedByStep.pop()
                    valuesUsed[valuesUsedByStep.pop()] = False
                    currentNumPossForEachSquare[currentSquareToChange] = 0
                    currentSquareToChange -= 1
                    currentNumPossForEachSquare[currentSquareToChange] += 1
                else:
                    valuesUsed[currentValue] = True
                    valuesUsedByStep.append(currentValue)
                    currentSquareToChange += 1
    return listOfAllValidCombForRow
def listAllValidCombForEachRow(board, squareNumsForEachRow):
    listOfAllValidCombForEachRow = []
    listOfValidValuesForEachSquare = listAllValidValuesForEachSquare(board)
    for row in range(9):
        listOfAllValidCombForEachRow.append(listAllValidCombForRow(board, row, listOfValidValuesForEachSquare, squareNumsForEachRow[row]))
    return listOfAllValidCombForEachRow
def calcPercentDone(amountOfPossCombForEachRow, currentCombNumForEachRow, currentRowToChange):
    multOfMax = 1
    sumOfMultOfMax = 0
    sumOfMultOfCurrent = Fraction(0, 1)
    for row in range(8, -1, -1):
        multOfMax *= amountOfPossCombForEachRow[row]
        sumOfMultOfMax += multOfMax
        if row <= currentRowToChange:
            sumOfMultOfCurrent += (Fraction((currentCombNumForEachRow[row]) / (amountOfPossCombForEachRow[row])))*multOfMax
    FractionAnswer = (sumOfMultOfCurrent / sumOfMultOfMax)*100
    DecimalAnswer = Decimal(FractionAnswer.numerator) / Decimal(FractionAnswer.denominator)
    return (DecimalAnswer)
def convertSecondsToString(numOfSeconds):
    numOfSecondsCopy = numOfSeconds
    Days = int(numOfSecondsCopy / 86400)
    numOfSecondsCopy -= Days*86400
    Hours = int(numOfSecondsCopy / 3600)
    numOfSecondsCopy -= Hours*3600
    Minutes = int(numOfSecondsCopy / 60)
    numOfSecondsCopy -= Minutes*60
    strSeconds = '{0:f}'.format(numOfSecondsCopy)
    lenStrSeconds = len(strSeconds)
    end = lenStrSeconds - 1
    start = 0
    if numOfSecondsCopy >= 10:
        start = 3
    else:
        start = 2
    for charNum in range(start, lenStrSeconds):
        if strSeconds[charNum] != "0":
            end = charNum + 1
            break
    strSeconds = strSeconds[:end]
    strToReturn = ""
    is60SecondsOrAbove = False
    if Days != 0:
        strToReturn += ("Days: " + str(Days) + ", ")
        is60SecondsOrAbove = True
    if (Hours != 0) or (Days != 0):
        strToReturn += ("Hours: " + str(Hours) + ", ")
        is60SecondsOrAbove = True
    if (Minutes != 0) or (Days != 0) or (Hours != 0):
        strToReturn += ("Minutes: " + str(Minutes) + ", ")
        is60SecondsOrAbove = True
    if numOfSecondsCopy < 0.0001 and (not(is60SecondsOrAbove)): strToReturn = "no_idea"
    else: strToReturn += ("Seconds: " + strSeconds)
    return(strToReturn)
def findSolutionToBoard(originalBoard):
    timeWastedOnUserInput = datetime.timedelta()
    solutionBoardToReturn = originalBoard.copy()
    allSolutionBoards = [] #just in case it's an invalid sudoku board with more than one solution
    squareNumsForEachRow = []
    for rowCounter in range(9):
        squareNumsForEachRow.append(fromRowToSquares(rowCounter))
    listOfAllValidCombForEachRow = listAllValidCombForEachRow(originalBoard, squareNumsForEachRow)
    amountOfPossCombForEachRow = [0]*9
    rowNumber = 0
    for rowCombinations in listOfAllValidCombForEachRow:
        lenOfRowComb = len(rowCombinations)
        if lenOfRowComb == 0: #is no solution to board
            return (allSolutionBoards, timeWastedOnUserInput, 100.0)
        amountOfPossCombForEachRow[rowNumber] = lenOfRowComb
        rowNumber += 1
    currentRowToChange = 0
    currentCombNumForEachRow = [0]*9
    aopcfer0 = amountOfPossCombForEachRow[0]
    askedUserToStop = False
    percentageToStopAt = Decimal(100)
    timeOfLastCheck = datetime.datetime.now()
    Seconds = datetime.timedelta(seconds = 2)
    counterOfWhile = 0
    timeStartOfWholeLoop = datetime.datetime.now()
    askedUserToStop1 = False
    while True:
        counterOfWhile += 1
        if counterOfWhile >= 100000:
            counterOfWhile = 0
            changeInTime = datetime.datetime.now() - timeOfLastCheck
            if changeInTime > Seconds:
                percentDone = calcPercentDone(amountOfPossCombForEachRow, currentCombNumForEachRow, currentRowToChange)
                if not(askedUserToStop):
                    timeUntilNowOfAlgWorking = (datetime.datetime.now() - timeStartOfWholeLoop) - timeWastedOnUserInput

                    numOfSecondsAltogether = (percentageToStopAt/percentDone)*(Decimal(timeUntilNowOfAlgWorking.total_seconds()))
                    estimatedTimeAltogether = datetime.timedelta(seconds = float(numOfSecondsAltogether))
                    timeUntilNowOfAlgWorkingSeconds = Decimal(timeUntilNowOfAlgWorking.total_seconds())
                    estimatedTimeRemainingSeconds = numOfSecondsAltogether - timeUntilNowOfAlgWorkingSeconds
                    estimatedTimeRemaining = convertSecondsToString(estimatedTimeRemainingSeconds)
                    numOfSolutions = len(allSolutionBoards)
                    print("Number of solutions so far: " + str(numOfSolutions) + "  " + str(percentDone) + "% done. ETA " + str(estimatedTimeRemaining))
                    if numOfSolutions >= 2:
                        startTimeUserInput = datetime.datetime.now()
                        askedUserToStop = True
                        inputIsValid = False
                        while not(inputIsValid):
                            inputIsValid = True
                            percentageToCompleteStr = input("\nThe program has already found " + str(numOfSolutions) + " solutions.\n" + \
                                     "Do you want to continue finding more solutions? (enter percentage of solutions to find, 0% for stop now, 100% for find all): ")
                            print("")
                            if len(percentageToCompleteStr) == 0:
                                print("invalid input for percentage, you inputted nothing.")
                                inputIsValid = False
                                continue
                            lastChar = percentageToCompleteStr[-1]
                            if lastChar == "%": percentageToCompleteStr = percentageToCompleteStr[:-1]
                            if len(percentageToCompleteStr) == 0:
                                print("invalid input for percentage. You didn\'t input any number.")
                                inputIsValid = False
                                continue
                            try:
                                percentageToStopAt = Decimal(percentageToCompleteStr)
                            except ValueError:
                                print("The percentage you entered isn\'t a floating poing number.")
                                inputIsValid = False
                                continue
                            if (percentageToStopAt < 0) or (percentageToStopAt > 100):
                                print("The percentage you entered is out of the 0-100 range.")
                                inputIsValid = False
                                continue
                        if percentageToStopAt == 0:
                            print("\nOk, stopping now.\nFinishing early, at " + str(percentDone) + "% done")
                            timeWastedOnUserInput = datetime.datetime.now() - startTimeUserInput
                            return (allSolutionBoards, timeWastedOnUserInput, percentDone)
                        elif percentageToStopAt == 100:
                            print("Ok, finding all solutions. this might take a while.\n")
                        else:
                            print("Ok, not exceeding finding " + str(percentageToStopAt) + "% of the solutions (not exact obviously)")
                        timeWastedOnUserInput = datetime.datetime.now() - startTimeUserInput
                    elif (numOfSolutions == 1) and not(askedUserToStop1):
                        askedUserToStop1 = True
                        startTimeUserInput1 = datetime.datetime.now()
                        if input("\nThe program has already found 1 solution.\nDo you want to continue trying to find more?(y/n): ") == "n":
                            timeWastedOnUserInput += (datetime.datetime.now() - startTimeUserInput1)
                            print("\nOk. Finishing early, at " + str(percentDone) + "% done.")
                            return (allSolutionBoards, timeWastedOnUserInput, percentDone)
                        else:
                            print("\nOk, Finding one more solution (and then asking you again to find more).")
                        print("")
                        timeWastedOnUserInput += (datetime.datetime.now() - startTimeUserInput1)
                else:
                    if percentDone > percentageToStopAt:
                        print("\nFinishing early, at " + str(percentDone) + "% done")
                        return (allSolutionBoards, timeWastedOnUserInput, percentDone)
                    else:
                        percentageToStopAtDividedByPercentDone = percentageToStopAt/percentDone
                        oneHundredDividedByPercentDone = Decimal(100)/percentDone
                        timeUntilNowOfAlgWorking = (datetime.datetime.now() - timeStartOfWholeLoop) - timeWastedOnUserInput
                        numOfSecondsAltogether = (percentageToStopAt/percentDone)*(Decimal(timeUntilNowOfAlgWorking.total_seconds()))
                        estimatedTimeAltogether = datetime.timedelta(seconds = float(numOfSecondsAltogether))
                        timeUntilNowOfAlgWorkingSeconds = Decimal(timeUntilNowOfAlgWorking.total_seconds())
                        estimatedTimeRemainingSeconds = numOfSecondsAltogether - timeUntilNowOfAlgWorkingSeconds
                        estimatedTimeRemaining = convertSecondsToString(estimatedTimeRemainingSeconds)
                        numOfSolutions = len(allSolutionBoards)
                        print("Number of solutions so far: " + str(numOfSolutions) + "  " + str(percentDone) + "% done. ETA " + estimatedTimeRemaining + \
                              "  Estimated total number of solutions: " + str(int(oneHundredDividedByPercentDone * numOfSolutions)))
                timeOfLastCheck = datetime.datetime.now()
        currentCombNum = currentCombNumForEachRow[currentRowToChange]
        if currentCombNum >= amountOfPossCombForEachRow[currentRowToChange]:
            if currentRowToChange == 0: break #exhausted all possibilities of row combinations
            currentCombNumForEachRow[currentRowToChange] = 0
            currentRowToChange -= 1
            squareNumsForCurrentRow = squareNumsForEachRow[currentRowToChange]
            for square in squareNumsForCurrentRow: solutionBoardToReturn[square] = originalBoard[square]
            currentCombNumForEachRow[currentRowToChange] += 1
        else:
            squareNum = 0
            loavcfercrtcccn = listOfAllValidCombForEachRow[currentRowToChange][currentCombNum]
            squareNumsForCurrentRow = squareNumsForEachRow[currentRowToChange]
            for square in squareNumsForCurrentRow:
                solutionBoardToReturn[square] = loavcfercrtcccn[squareNum]
                squareNum += 1
            if isBoardValidBasedOnChangedRow(solutionBoardToReturn, currentRowToChange):
                if currentRowToChange == 8:
                    allSolutionBoards.append(solutionBoardToReturn.copy())
                    squareNumsForCurrentRow = squareNumsForEachRow[currentRowToChange]
                    for square in squareNumsForCurrentRow: solutionBoardToReturn[square] = originalBoard[square]
                    currentCombNumForEachRow[currentRowToChange] = 0
                    currentRowToChange -= 1
                    squareNumsForCurrentRow7 = squareNumsForEachRow[currentRowToChange]
                    for square7 in squareNumsForCurrentRow7: solutionBoardToReturn[square7] = originalBoard[square7]
                    currentCombNumForEachRow[currentRowToChange] += 1
                else:
                    currentRowToChange += 1
            else:
                squareNumsForCurrentRow = squareNumsForEachRow[currentRowToChange]
                for square in squareNumsForCurrentRow: solutionBoardToReturn[square] = originalBoard[square]
                currentCombNumForEachRow[currentRowToChange] += 1
    print("\n100% done!!!" + "  Number of solutions so far: " + str(len(allSolutionBoards)))
    return (allSolutionBoards, timeWastedOnUserInput, 100.0)
board = createBoard()
startTime = datetime.datetime.now()
print("\nCalculating...")
allSolutionBoards, timeWastedOnUserInput, percentageOfSolutionCompleted = findSolutionToBoard(board)
timeTook = datetime.datetime.now() - startTime
timeTook -= timeWastedOnUserInput
numOfSolutions = len(allSolutionBoards)
toPrintToFile = False
print("Calculations completed in " + str(timeTook) + "  (Not including time of user input)\n" + \
      "                          H M  Seconds\n\n" + \
      "Percentage of solutions that the program checked: " + str(percentageOfSolutionCompleted) + "%\n\n" + \
      "Original board that I needed to solve:\n" + createStringOfBoard(board) + "\n\n")
print("Final Solution:\n")
if numOfSolutions == 0: print("No Solutions")
elif numOfSolutions == 1:
    if percentageOfSolutionCompleted == 100:
        print("Valid board, there\'s only one solution:")
    else:
        print("Whether the board is valid or invalid is unknown.\nOnly one solution was found, but that doesn't mean that it\'s the only one that exists:")
    printBoard(allSolutionBoards[0])
    print("")
    if input("do you want to write the solution into a text file?(y/n): ") == "y": toPrintToFile = True
else:
    print("Invalid board, it has " + str(len(allSolutionBoards)) + " solutions. for example:\nsolution 1:")
    printBoard(allSolutionBoards[0])
    print("\n\nsolution 2:")
    printBoard(allSolutionBoards[1])
    print("")
    if numOfSolutions > 2:
        if input("do you want to print the rest of the solutions?(y/n): ") == "y":
            for solutionNum in range(2, numOfSolutions):
                print("\n\nsolution " + str(solutionNum + 1) + ":")
                printBoard(allSolutionBoards[solutionNum])
                print("")
    if input("do you want to write all solutions into a text file?(y/n): ") == "y": toPrintToFile = True
if toPrintToFile:
    inputFileNameAgain = True
    nameOfFile = ""
    while inputFileNameAgain:
        inputFileNameAgain = True
        nameOfFile = input("what do you want to call the file?(with .txt): ")
        try:
            fileOfSolutionsTry = open(nameOfFile)
            fileOfSolutionsTry.close()
            print("\nThe file with the directory / file name:\n" + nameOfFile + "\nalready exists. Try using a different directory / file name.\n")
        except FileNotFoundError:
            inputFileNameAgain = False
    fileOfSolutions = open(nameOfFile, "w")
    fileOfSolutions.write("Calculations completed in " + str(timeTook) + "  (Not including time of user input)\n" + \
                          "                          H M  Seconds\n\n" + \
                          "Percentage of solutions that the program checked: " + str(percentageOfSolutionCompleted) + "%\n\n" + \
                          "Original board that I needed to solve:\n" + createStringOfBoard(board) + \
                          "\n\nNumber of solutions found: " + str(numOfSolutions) )
    if percentageOfSolutionCompleted == 0:
        fileOfSolutions.write("It is unknown whether the board is valid or invalid")
    for solutionNum in range(numOfSolutions):
        fileOfSolutions.write("\n\nsolution " + str(solutionNum + 1) + ":\n" + (createStringOfBoard(allSolutionBoards[solutionNum]) + "\n"))
    fileOfSolutions.close()
    print("\nFinished writing the solutions into the text file.")
input("\npress enter to exit program")


import unittest

from coorblimey.geocentrics import Geocentrics

class TestGeocentrics(unittest.TestCase):

    def test_to_geographic(self):
        geo      = Geocentrics(1418595, -689557, -6159338)
        lat_long = geo.make_geographic()
        self.assertEqual(lat_long, [-75.7283616724, -25.9236668699, 30.705])

if __name__ == "__main__":
    unittest.main()


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import os

from mozperftest.test.browsertime import add_option, add_options

sites = os.path.join(os.path.dirname(__file__), "sites.txt")
with open(sites) as f:
    sites = [site for site in f.read().split("\n") if site.strip()]

def next_site():
    for site in sites:
        yield site

get_site = next_site()

options = [
    ("firefox.preference", "network.http.speculative-parallel-limit:6"),
    # XXX potentially move those as first class options in mozperf?
    ("pageCompleteWaitTime", "10000"),
    ("visualMetrics", "true"),
    ("video", "true"),
    ("firefox.windowRecorder", "false"),
    ("videoParams.addTimer", "false"),
    ("videoParams.createFilmstrip", "false"),
    ("videoParams.keepOriginalVideo", "true"),
]

def before_runs(env, **kw):
    env.set_arg("cycles", len(sites))
    add_options(env, options)

def before_cycle(env, **kw):
    url = next(get_site)
    add_option(env, "browsertime.url", url)