"""Common fixutres with default mocks as well as common test helper methods."""
from unittest.mock import patch

import pytest
import tesla_wall_connector

from homeassistant.components.tesla_wall_connector.const import DOMAIN
from homeassistant.const import CONF_HOST, CONF_SCAN_INTERVAL
from homeassistant.core import HomeAssistant

from tests.common import MockConfigEntry

@pytest.fixture
def mock_wall_connector_version():
    """Fixture to mock get_version calls to the wall connector API."""

    with patch(
        "tesla_wall_connector.WallConnector.async_get_version",
        return_value=get_default_version_data(),
    ):
        yield

def get_default_version_data():
    """Return default version data object for a wall connector."""
    return tesla_wall_connector.wall_connector.Version(
        {
            "serial_number": "abc123",
            "part_number": "part_123",
            "firmware_version": "1.2.3",
        }
    )

async def create_wall_connector_entry(
    hass: HomeAssistant, side_effect=None
) -> MockConfigEntry:
    """Create a wall connector entry in hass."""
    entry = MockConfigEntry(
        domain=DOMAIN,
        data={CONF_HOST: "1.2.3.4"},
        options={CONF_SCAN_INTERVAL: 30},
    )

    entry.add_to_hass(hass)

    # We need to return vitals with a contactor_closed attribute
    # Since that is used to determine the update scan interval
    fake_vitals = tesla_wall_connector.wall_connector.Vitals(
        {
            "contactor_closed": "false",
        }
    )

    with patch(
        "tesla_wall_connector.WallConnector.async_get_version",
        return_value=get_default_version_data(),
        side_effect=side_effect,
    ), patch(
        "tesla_wall_connector.WallConnector.async_get_vitals",
        return_value=fake_vitals,
        side_effect=side_effect,
    ), patch(
        "tesla_wall_connector.WallConnector.async_get_lifetime",
        return_value=None,
        side_effect=side_effect,
    ):
        await hass.config_entries.async_setup(entry.entry_id)
        await hass.async_block_till_done()

    return entry


'''
문제 : 경로 찾기
난이도 : 실버1

가중치가 없는 방향 그래프가 주어졌을 때 모든 정점에 대해서
i에서 j로 가는 경로가 *있는지 없는지* 구하는 프로그램

'''
import sys
from collections import deque

n = int(sys.stdin.readline())

# 그래프 인접 행렬 입력
graph = [list(map(int, sys.stdin.readline().split())) for _ in range(n)]
visited = [[0]*n for _ in range(n)]

def bfs(x):
    queue = deque()
    queue.append(x)
    check = [0 for _ in range(n)]

    while queue:
        q = queue.popleft()

        for i in range(n):
            if check[i] == 0 and graph[q][i] == 1:
                queue.append(i)
                check[i] = 1
                visited[x][i] = 1

for i in range(0, n):
    bfs(i)

for i in visited:
    print(*i)


from datetime import datetime, timedelta, date
from copy import deepcopy
from collections import OrderedDict, defaultdict, Callable
from flask import render_template, current_app, request
import plotly
import pandas as pd
import numpy as np
from sqlalchemy import func
from sqlalchemy.orm import aliased

from .common.base import BaseView
from .common.function import *
from db import *

def get_current_team_cats_count(cats):
    cat_filter = or_(1==2)
    for cat in cats:
        cat_filter = or_(cat_filter, Issue.category==Category.query.filter_by(c_name=cat).first())

    status_filter = or_(Issue.state==State.query.filter_by(s_name='Ongoing').first(), \
        Issue.state==State.query.filter_by(s_name='New').first())

    ret = Issue.query.filter(and_(status_filter, cat_filter )). \
                        add_columns(func.count(Issue.team_id)).group_by(Issue.team_id).all()
    team_name = []
    team_count = []
    for x, c in ret:
        team_name.append(x.team.g_name)
        team_count.append(c)
    return team_name, team_count

def get_days_cats_team_count(cats, from_date, to_date):
    teams = [x[0] for x in Group.query.filter_by(in_ps=True).with_entities(Group.g_name).all()]
    Group_T = aliased(Issue.team)
    date_filter = and_(Issue.out_date >= from_date, Issue.out_date <= to_date)

    cat_filter = or_(1==2)
    for cat in cats:
        cat_filter = or_(cat_filter, Issue.category==Category.query.filter_by(c_name=cat).first())

    ret = Issue.query.filter(and_(date_filter, cat_filter) ).outerjoin(Group_T, Issue.team).with_entities( \
            Group_T.g_name.label('team'), Issue.out_date).add_columns(func.count(Issue.out_date)).\
                group_by(Issue.out_date, 'team').all()
    res = dict()
    day_cal = (to_date - from_date).days + 1
    for x in teams:
        days = [from_date+timedelta(days=i) for i in range(day_cal)]
        res[x] = OrderedDict(zip(days, [0]*day_cal))
    for team, day, count in ret:
        res[team][day]=count
    counts = []
    for team in teams:
        counts.append(list())
        for day, count in res[team].items():
            counts[-1].append(count)

    return teams, counts

def moving_average(a, n=4) :
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n

def get_weeks_cats_team_count(cats, from_date, to_date, mo_avg=False):
    day_cal = (to_date - from_date).days + 1
    week_cal = int(day_cal / 7)
    teams, counts = get_days_cats_team_count(cats, from_date, to_date)
    for t in range(len(teams)):
        tmp_list = []
        for w in range(week_cal):
            tmp_list.append(sum(counts[t][w*7:(w*7+7)]))
        counts[t] = deepcopy(tmp_list)
        if mo_avg:
            counts[t] = list(moving_average(counts[t]))
    return teams, counts

def get_productivity(teams, counts, to_date):
    week_cal = len(counts[0])
    oldest_day = to_date - timedelta(days=(week_cal-1)*7)
    for k, team in enumerate(teams):
        member_json = Group.query.filter_by(g_name=team).with_entities(Group.member).first()[0]
        j = 0
        for i in range(0, week_cal*7, 7):
            tmp_day = oldest_day+timedelta(days=i)
            # print(team, tmp_day, member_json)
            team_count = get_team_member(member_json, tmp_day)
            counts[k][j] /= team_count
            j += 1
    return teams, counts

class OrderedDefaultdict(OrderedDict):
    def __init__(self, default_factory=None, *args, **kwargs):
        if not (default_factory is None
                or isinstance(default_factory, Callable)):
            raise TypeError('first argument must be callable or None')
        super(OrderedDefaultdict, self).__init__(*args, **kwargs)
        self.default_factory = default_factory

    def __missing__(self, key):
        if self.default_factory is None:
            raise KeyError(key,)
        self[key] = value = self.default_factory()
        return value

def get_weeks_cycle_time(cats, from_date, to_date):
    teams = [x[0] for x in Group.query.filter_by(in_ps=True).with_entities(Group.g_name).all()]
    Group_T = aliased(Issue.team)
    day_cal = (to_date - from_date).days + 1
    week_cal = int(day_cal / 7)
    date_filter = and_(Issue.out_date >= from_date, Issue.out_date <= to_date)

    cat_filter = or_(1==2)
    for cat in cats:
        cat_filter = or_(cat_filter, Issue.category==Category.query.filter_by(c_name=cat).first())

    ret = Issue.query.filter(and_(date_filter, cat_filter) ).outerjoin(Group_T, Issue.team).with_entities( \
            Group_T.g_name.label('team'), Issue.out_date, Issue.in_date).all()

    # assert current_app.debug == False
    res = dict()
    for team in teams:
        days = [from_date+timedelta(days=i) for i in range(day_cal)]
        res[team] = OrderedDict(zip(days, [[] for _ in range(day_cal)]))
    for team, out_day, in_day in ret:
        res[team][out_day].append(in_day)
    counts = []
    for team in teams:
        counts.append(list())
        for outday, in_day_list in res[team].items():
            total_day_count = 0
            total_count = 0
            for one_in_day in in_day_list:
                total_day_count += (outday - one_in_day).days
                total_count += 1
            counts[-1].append((total_count, total_day_count))

    week_counts = []
    for team_counts in counts:
        week_counts.append([])
        for week in range(week_cal):
            count_total_list = list(zip(*team_counts[week*7:week*7+7]))
            week_total_count = sum(count_total_list[1])
            week_count = sum(count_total_list[0])
            week_counts[-1].append(week_total_count/week_count if week_count else 0)

    return teams, week_counts

class MetricView(BaseView):
    def get(self, m_id=None):
        # assert current_app.debug == False
        if m_id is None:
            categories = Category.select()
            return render_template('metric.html', categories=categories)
        else:
            args = dict(request.args)
            from_date = args.pop('from_date')[0] if 'from_date' in args else ''
            to_date = args.pop('to_date')[0] if 'to_date' in args else ''
            cats = list(args.keys())

            if m_id == 1:
                team_name, team_count = get_current_team_cats_count(cats)
                fig = {
                    'data': [{
                        'labels': team_name,
                        'values': team_count,
                        'type': 'pie'
                    }],
                    'layout': {'title': 'LRC New/Ongoing '+' '.join(cats)}
                }
                return get_json(fig), 200

            elif m_id == 2:
                if from_date and to_date:
                    from_date = date(*map(int, from_date.split('-')))
                    to_date = date(*map(int, to_date.split('-')))
                    day_cal = (to_date - from_date).days + 1
                else:
                    to_date = date.today()
                    day_cal = 30
                    from_date = to_date - timedelta(days=day_cal-1)

                teams, counts = get_days_cats_team_count(cats, from_date, to_date)
                x = [str(from_date+timedelta(days=i)) for i in range(day_cal)]

                data = []
                for i in range(len(teams)):
                    data.append({
                        'x':  x,
                        'y': counts[i],
                        'name':  teams[i],
                        'mode':  'lines+markers',
                        'line': {
                            'shape':  'spline'
                        }
                    })
                layout = dict(title = 'Resolved '+' '.join(cats) + '(in 30 days)',
                            xaxis = dict(title = 'Date'),
                            yaxis = dict(title = 'Resolved count'),
                            )
                fig = dict(data=data, layout=layout)
                return get_json(fig), 200

            elif m_id == 3:
                if from_date and to_date:
                    from_date = date(*map(int, from_date.split('-')))
                    to_date = date(*map(int, to_date.split('-')))
                    day_cal = (to_date - from_date).days + 1
                else:
                    to_date = date.today()
                    day_cal = 30
                    from_date = to_date - timedelta(days=day_cal-1)

                teams, counts = get_days_cats_team_count(cats, from_date, to_date)
                x = [str(from_date+timedelta(days=i)) for i in range(day_cal)]

                data = []
                for i in range(len(teams)):
                    data.append({
                        'x' : x,
                        'y' : counts[i],
                        'name' : teams[i],
                        'type': 'bar'
                    })
                layout = dict(title = 'Daily PS/Team relative resolved ' +' '.join(cats),
                            xaxis = dict(title = 'Date'),
                            yaxis = dict(title = 'Resolved count'),
                            barmode = 'relative'
                            )
                fig = dict(data=data, layout=layout)
                return get_json(fig), 200

            elif m_id == 4:
                if to_date:
                    to_date = date(*map(int, to_date.split('-')))
                else:
                    to_date = date.today()
                week_cal = 17
                day_cal = week_cal * 7
                from_date = to_date - timedelta(days=day_cal-1)

                teams, counts = get_weeks_cats_team_count(cats, from_date, to_date, mo_avg=True)
                teams.append('PS Total')

                week_count = len(counts[0])
                ps_total = [0]*week_count
                for team in counts:
                    for i in range(week_count):
                        ps_total[i] += team[i]
                counts.append(ps_total)

                x = []
                for i in range(0, week_cal*7, 7):
                    tmp = (from_date+timedelta(days=i)).isocalendar()[:2]
                    x.append(str(tmp[0])+'-'+str(tmp[1]))

                data = []
                for i in range(len(teams)):
                    data.append({
                        'x': x,
                        'y': counts[i],
                        'name': teams[i],
                        'mode': 'lines+markers',
                        'shape': 'spline',
                        'line': {
                            'shape':  'spline'
                        }
                    })
                layout = dict(title = 'Resolved '+' '.join(cats) + ' (Rolling Average of 4 weeks)',
                            xaxis = dict(title = 'Week'),
                            yaxis = dict(title = 'Resolved count'),
                            )
                fig = dict(data=data, layout=layout)
                return get_json(fig), 200

            elif m_id == 5:
                if to_date:
                    to_date = date(*map(int, to_date.split('-')))
                else:
                    to_date = date.today()
                week_cal = 14
                day_cal = week_cal * 7
                from_date = to_date - timedelta(days=day_cal-1)

                teams, counts = get_weeks_cats_team_count(cats, from_date, to_date)
                teams, counts = get_productivity(teams, counts, to_date)

                x = []
                for i in range(0, week_cal*7, 7):
                    tmp = (from_date+timedelta(days=i)).isocalendar()[:2]
                    x.append(str(tmp[0])+'-'+str(tmp[1]))

                data = []
                for i in range(len(teams)):
                    data.append({
                        'x': x,
                        'y': counts[i],
                        'name': teams[i],
                        'mode': 'lines+markers',
                        'shape': 'spline',
                        'line': {
                            'shape':  'spline'
                        }
                    })
                layout = dict(title = 'Team productivity of '+' '.join(cats),
                            xaxis = dict(title = 'Week'),
                            yaxis = dict(title = 'Productivity'),
                            )
                fig = dict(data=data, layout=layout)
                return get_json(fig), 200

            elif m_id == 6:
                if to_date:
                    to_date = date(*map(int, to_date.split('-')))
                else:
                    to_date = date.today()
                week_cal = 14
                day_cal = week_cal * 7
                from_date = to_date - timedelta(days=day_cal-1)

                teams, counts = get_weeks_cycle_time(cats, from_date, to_date)

                x = []
                for i in range(0, week_cal*7, 7):
                    tmp = (from_date+timedelta(days=i)).isocalendar()[:2]
                    x.append(str(tmp[0])+'-'+str(tmp[1]))

                data = []
                for i in range(len(teams)):
                    data.append({
                        'x': x,
                        'y': counts[i],
                        'name': teams[i],
                        'mode': 'lines+markers',
                        'shape': 'spline',
                        'line': {
                            'shape':  'spline'
                        }
                    })
                layout = dict(title = 'Team Cycle Time of '+' '.join(cats),
                            xaxis = dict(title = 'Week'),
                            yaxis = dict(title = 'Cycle Time (days)'),
                            )
                fig = dict(data=data, layout=layout)
                return get_json(fig), 200


import re
import os
import pdb
import glob
import pprint
import logging
import subprocess
import bs4 as bs
import numpy as np
import pandas as pd
import xarray as xr
import linecache as lc
import urllib.request
from functools import reduce
from geopy.distance import distance
from time import perf_counter, sleep
from contextlib import contextmanager
from .parsing_instructions import fort15_instructions
from .adcirc_param_parser import ParamParser

P_CONFIGS = {}
pd.options.display.float_format = "{:,.10f}".format
logger = logging.getLogger()

@contextmanager
def timing(label: str):
    t0 = perf_counter()
    yield lambda: (label, t1 - t0)
    t1 = perf_counter()

def get_def(param: str):
    try:
        desc = P_CONFIGS[param]
        pprint.pp(f"{param} = {desc}")
    except:
        print(f"Did not find parameter {param}'")
        pass

def update_param_configs(url: str):
    global P_CONFIGS

    P_CONFIGS = pull_param_configs(url)

def pull_param_configs(
    url: str = "https://adcirc.org/home/documentation/users-manual-v53/parameter-definitions",
):
    params = {}
    try:
        source = urllib.request.urlopen(url).read()
        rows = bs.BeautifulSoup(source, "lxml").findAll("p", {"class": "MsoNormal"})
        for row in rows:
            p_name = row.text.split()[0]
            if "(" in p_name:
                p_name = p_name.split("(")[0]
            params[p_name] = " ".join(row.text.split()[2:])
    except:
        pass

    return params

def read_param_line(out, params, f, ln=None, dtypes=None):
    if ln:
        line = lc.getline(f, ln)
    else:
        line = f.readline().strip()
    logger.info(",".join(params) + " : " + line)
    vals = [x for x in re.split("\\s+", line) if x != ""]
    for i in range(len(params)):
        try:
            if dtypes:
                out.attrs[params[i]] = dtypes[i](vals[i])
            else:
                out.attrs[params[i]] = vals[i]
        except ValueError:
            out.attrs[params[i]] = np.nan

    if ln:
        ln += 1
        return out, ln
    else:
        return out

def read_text_line(out, param, f, ln=None):
    if ln:
        line = lc.getline(f, ln).strip()
    else:
        line = f.readline().strip()
    logger.info(param + " : " + line)
    out.attrs[param] = line
    if ln:
        ln += 1
        return out, ln
    else:
        return out

def write_numeric_line(vals, f):
    line = " ".join([str(v) for v in vals])
    f.write(line + "\n")

def write_param_line(ds, params, f):
    if type(ds) == xr.Dataset:
        line = " ".join([str(ds.attrs[p]) for p in params])
    else:
        line = " ".join([str(x) for x in ds])
    if len(line) < 80:
        line += ((80 - len(line)) * " ") + "! " + ",".join(params)
    else:
        logger.warning("WARNING - fort config files shouldn't be wider than 80 cols!")
    logger.info("Writing param line for " + ",".join(params) + " - " + line)
    f.write(line + "\n")

def write_text_line(ds, param, f):
    if type(ds) == xr.Dataset:
        line = ds.attrs[param]
    else:
        line = ds
    logger.info("Writing text line for " + param + " - " + line)
    if len(line) < 80:
        if param != "":
            line += ((80 - len(line)) * " ") + "! " + param
    else:
        logger.warning("WARNING - fort config files shouldn't be wider than 80 cols!")
    f.write(line + "\n")

def find_closest(x, y, x_t, y_t):
    closest = 1e20
    closest_idx = None
    logger.info(f"Searching {len(x)} nodes for closest node to {x_t},{y_t}")
    for i, v in enumerate(zip(x, y)):

        dis = distance(v, (x_t, y_t)).km
        if dis < closest:
            closest = dis
            closest_idx = i

    logger.info(
        f"Found closest at index {closest_idx} and coordiante {x.item(closest_idx)}, {y.item(closest_idx)} with distance :{closest}"
    )
    return closest_idx

def get_latest_ts(path: str):
    if "\n" in path:
        tail = path
    else:
        res = subprocess.run(["tail", path], stdout=subprocess.PIPE)
        if res.returncode != 0:
            raise Exception("Unable to access adcirc.log file.")
        tail = res.stdout.decode("utf-8")
    for line in reversed(tail.split("\n")):
        split = re.split("TIME STEP = ", line)
        if len(split) > 1:
            ts = split[1].split(" ")[1]
            return ts
    raise Exception("adcirc.log found but time stepping hasn't started yet.")

def snatch_fort14_params(fname):
    """Read a few key parameters from the fort.14 file - not the actual mesh
    """

    res = {}
    with open(fname, "r") as fp:
        fp.readline()
        res["NE"], res["NP"] = map(int, fp.readline().strip().split()[:2])
        for i in range(res["NE"] + res["NP"]): fp.readline()
        res["NOPE"] = int(fp.readline().split()[0])
        res["NETA"] = int(fp.readline().split()[0])

    return res

def read_fort14(f14_file, ds=None):
    """read_fort14.
  Reads in ADCIRC fort.14 f14_file

  :param f14_file: Path to Python file.
  """
    if type(ds) != xr.Dataset:
        ds = xr.Dataset()

    # 1 : AGRID = alpha-numeric grid identification (<=24 characters).
    ds, ln = read_text_line(ds, "AGRID", f14_file, ln=1)

    # 2 : NE, NP = number of elements, nodes in horizontal grid
    ds, ln = read_param_line(ds, ["NE", "NP"], f14_file, ln=ln, dtypes=2 * [int])

    # 3-NP : NODES
    # for k=1 to NP
    #    JN, X(JN), Y(JN), DP(JN)
    # end k loop
    logger.info("Reading Node Map.")
    ds = xr.merge(
        [
            ds,
            pd.read_csv(
                f14_file,
                delim_whitespace=True,
                nrows=ds.attrs["NP"],
                skiprows=ln - 1,
                header=None,
                names=["JN", "X", "Y", "DP"],
            )
            .set_index("JN")
            .to_xarray(),
        ],
        combine_attrs="override",
    )
    ln += ds.attrs["NP"]

    # (2+NP)-(2+NP+NE) : ELEMENTS
    # for k=1 to NE
    #    JE, NHY, NM(JE,1),NM(JE,2), NM(JE,3)
    # end k loop
    logger.info("Reading Element Map.")
    ds = xr.merge(
        [
            ds,
            pd.read_csv(
                f14_file,
                delim_whitespace=True,
                nrows=ds.attrs["NE"],
                skiprows=ln - 1,
                header=None,
                names=["JE", "NHEY", "NM_1", "NM_2", "NM_3"],
            )
            .set_index("JE")
            .to_xarray(),
        ],
        combine_attrs="override",
    )
    ln += ds.attrs["NE"]

    # (3+NP+NE) : NOPE = number of elevation specified boundary forcing segments.
    ds, ln = read_param_line(ds, ["NOPE"], f14_file, ln=ln, dtypes=[int])

    # (4+NP+NE) : NETA = total number of elevation specified boundary nodes
    ds, ln = read_param_line(ds, ["NETA"], f14_file, ln=ln, dtypes=[int])

    # Rest of the file contains boundary information. Read all at once
    bounds = pd.read_csv(
        f14_file, delim_whitespace=True, header=None, skiprows=ln - 1, usecols=[0]
    )
    bounds["BOUNDARY"] = None
    bounds["IBTYPEE"] = None
    bounds["IBTYPE"] = None
    bounds = bounds.rename(columns={0: "BOUNDARY_NODES"})

    # Get elevation sepcified boundary forcing segments
    bnd_idx = 0
    for i in range(ds.attrs["NOPE"]):
        sub = xr.Dataset()
        logger.info("Reading NOPE #" + str(i))

        # NVDLL(k), IBTYPEE(k) = number of nodes, and boundary type
        sub, ln = read_param_line(
            sub, ["NVDLL", "IBTYPEE"], f14_file, ln=ln, dtypes=2 * [int]
        )
        bounds = bounds.drop(bnd_idx)
        bounds.loc[bnd_idx : bnd_idx + sub.attrs["NVDLL"], "BOUNDARY"] = i
        bounds.loc[bnd_idx : bnd_idx + sub.attrs["NVDLL"], "IBTYPEE"] = sub.attrs[
            "IBTYPEE"
        ]
        ln += sub.attrs["NVDLL"]
        bnd_idx += sub.attrs["NVDLL"] + 1

    bounds["BOUNDARY_NODES"] = bounds["BOUNDARY_NODES"].astype(int)
    elev_bounds = bounds[["BOUNDARY", "BOUNDARY_NODES", "IBTYPEE"]].dropna()
    elev_bounds["ELEV_BOUNDARY"] = elev_bounds["BOUNDARY"].astype(int)
    elev_bounds["ELEV_BOUNDARY_NODES"] = elev_bounds["BOUNDARY_NODES"].astype(int)
    elev_bounds["IBTYPEE"] = elev_bounds["IBTYPEE"].astype(int)
    elev_bounds = elev_bounds.drop(["BOUNDARY", "BOUNDARY_NODES"], axis=1)
    ds = xr.merge(
        [ds, elev_bounds.set_index("ELEV_BOUNDARY").to_xarray()],
        combine_attrs="override",
    )

    # NBOU = number of normal flow (discharge) specified boundary segments
    bounds = bounds.drop(bnd_idx)
    bnd_idx += 1
    ds, ln = read_param_line(ds, ["NBOU"], f14_file, ln=ln, dtypes=[int])

    # NVEL = total number of normal flow specified boundary nodes
    bounds = bounds.drop(bnd_idx)
    bnd_idx += 1
    ds, ln = read_param_line(ds, ["NVEL"], f14_file, ln=ln, dtypes=[int])

    # Get flow sepcified boundary segments
    for i in range(ds.attrs["NBOU"]):
        logger.info("Reading NBOU #" + str(i))

        # NVELL(k), IBTYPE(k)
        sub, ln = read_param_line(
            sub, ["NVELL", "IBTYPE"], f14_file, ln=ln, dtypes=2 * [int]
        )
        bounds = bounds.drop(bnd_idx)
        bounds.loc[bnd_idx : bnd_idx + sub.attrs["NVELL"], "BOUNDARY"] = (
            i + ds.attrs["NOPE"]
        )
        bounds.loc[bnd_idx : bnd_idx + sub.attrs["NVELL"], "IBTYPE"] = sub.attrs[
            "IBTYPE"
        ]
        ln += sub.attrs["NVELL"]
        bnd_idx += sub.attrs["NVELL"] + 1

    normal_bounds = bounds[["BOUNDARY", "BOUNDARY_NODES", "IBTYPE"]].dropna()
    normal_bounds["NORMAL_BOUNDARY"] = (
        normal_bounds["BOUNDARY"].astype(int) - ds.attrs["NOPE"]
    )
    normal_bounds["NORMAL_BOUNDARY_NODES"] = normal_bounds["BOUNDARY_NODES"].astype(int)
    normal_bounds["IBTYPE"] = normal_bounds["IBTYPE"].astype(int)
    normal_bounds = normal_bounds.drop(["BOUNDARY", "BOUNDARY_NODES"], axis=1)
    ds = xr.merge(
        [ds, normal_bounds.set_index("NORMAL_BOUNDARY").to_xarray()],
        combine_attrs="override",
    )

    return ds

def read_fort15(f15_file, ds=None):
    """read_fort15.
    Reads in ADCIRC fort.15 f15_file

    Args:
        f15_file (str) - Path to parameter file.
        ds (dict) - a dictionary with parameter data
    """

    if ds is None:
        ds = {}

    if "NETA" not in ds:
        # we need NETA in order to parse the fort15 file
        # Try to find the fort.14 file
        dirname = os.path.dirname(f15_file)
        f14_file = dirname + "/fort.14" if dirname else "fort.14"
        if os.path.exists(f14_file):
            ds.update(snatch_fort14_params(f14_file))
        else:
            raise ValueError("NETA must be provided in order to parse the fort.15 file!"
                f"Tried and failed to find the fort.14 file in the directory '{dirname}'!")

    parser = ParamParser(fort15_instructions)
    return parser.parse(f15_file, starting_params=ds)

def read_fort13(f13_file, ds=None):
    if type(ds) != xr.Dataset:
        ds = xr.Dataset()

    ds, ln = read_param_line(ds, ["AGRID"], f13_file, ln=1)

    # Note this must match NP
    ds, ln = read_param_line(ds, ["NumOfNodes"], f13_file, ln=ln, dtypes=[int])

    # Note this must be >= NWP
    ds, ln = read_param_line(ds, ["NAttr"], f13_file, ln=ln, dtypes=[int])

    # Read Nodal Attribute info
    nodals = []
    for i in range(ds.attrs["NAttr"]):
        tmp, ln = read_param_line(xr.Dataset(), ["AttrName"], f13_file, ln=ln)
        tmp, ln = read_param_line(tmp, ["Units"], f13_file, ln=ln)
        tmp, ln = read_param_line(tmp, ["ValuesPerNode"], f13_file, ln=ln, dtypes=[int])
        tmp, ln = read_param_line(
            tmp,
            ["v" + str(i) for i in range(tmp.attrs["ValuesPerNode"])],
            f13_file,
            ln=ln,
            dtypes=tmp.attrs["ValuesPerNode"] * [float],
        )
        nodals.append(tmp.attrs)
    ds = xr.merge(
        [ds, pd.DataFrame(nodals).set_index("AttrName").to_xarray()],
        combine_attrs="override",
    )

    # Read Non Default Nodal Attribute Values
    non_default = []
    line = lc.getline(f13_file, ln)
    while line != "":
        tmp, ln = read_param_line(tmp, ["AttrName"], f13_file, ln=ln)
        tmp, ln = read_param_line(tmp, ["NumND"], f13_file, ln=ln, dtypes=[int])

        num_vals = ds["ValuesPerNode"][ds["AttrName"] == tmp.attrs["AttrName"]].values[
            0
        ]
        cols = ["JN"] + [
            "_".join([tmp.attrs["AttrName"], str(x)]) for x in range(num_vals)
        ]
        tmp_df = pd.read_csv(
            f13_file,
            skiprows=ln - 1,
            nrows=tmp.attrs["NumND"],
            delim_whitespace=True,
            names=cols,
        )
        non_default.append(tmp_df)
        ln += tmp.attrs["NumND"]
        line = lc.getline(f13_file, ln)
    ds = xr.merge(
        [
            ds,
            reduce(lambda x, y: x.merge(y, how="outer"), non_default)
            .set_index("JN")
            .to_xarray(),
        ],
        combine_attrs="override",
    )

    return ds

def read_fort22(f22_file, NWS=12, ds=None):
    if type(ds) == xr.Dataset:
        if "NWS" in ds.attrs.keys():
            NWS = ds.attrs["NWS"]
    else:
        ds = xr.Dataset()

    if NWS in [12, 12012]:
        ds, _ = read_param_line(ds, ["NWSET"], f22_file, ln=1, dtypes=[float])
        ds, _ = read_param_line(ds, ["NWBS"], f22_file, ln=2, dtypes=[float])
        ds, _ = read_param_line(ds, ["DWM"], f22_file, ln=3, dtypes=[float])
    else:
        msg = f"NWS {NWS} Not yet implemented!"
        logger.error(msg)
        raise Exception(msg)

    return ds

def read_fort24(f22_file, ds=None):
    if type(ds) != xr.Dataset:
        ds = xr.Dataset()

    data = pd.read_csv(
        f22_file,
        delim_whitespace=True,
        names=["JN", "SALTAMP", "SALTPHA"],
        low_memory=False,
        header=None,
    )
    tides = data[data["SALTPHA"].isna()]
    all_tmp = []
    for i in range(int(tides.shape[0] / 4)):
        stop = (tides.index[(i + 1) * 4] - 1) if i != 7 else data.index[-1]
        tmp = data.loc[(tides.index[i * 4 + 3] + 1) : stop][
            ["JN", "SALTAMP", "SALTPHA"]
        ].copy()
        tmp["JN"] = tmp["JN"].astype(int)
        tmp["SALTAMP"] = tmp["SALTAMP"].astype(float)
        tmp["SALTPHA"] = tmp["SALTPHA"].astype(float)
        tmp["SALTFREQ"] = float(tides["JN"].iloc[i * 4 + 1])
        tmp = tmp.set_index("JN").to_xarray()
        tmp = tmp.expand_dims(dim={"SALTNAMEFR": [tides["JN"].iloc[i * 4 + 3]]})
        all_tmp.append(tmp)

    ds = xr.merge([ds, xr.concat(all_tmp, "SALTNAMEFR")], combine_attrs="override")

    return ds

def read_fort25(f25_file, NWS=12, ds=None):
    if ds != None:
        if "NWS" in ds.attrs.keys():
            NWS = ds.attrs["NWS"]
    else:
        ds = xr.Dataset()

    if NWS in [12, 12012]:
        ds, _ = read_param_line(ds, ["NUM_ICE_FIELDS"], f25_file, ln=1, dtypes=[float])
        ds, _ = read_param_line(
            ds, ["NUM_BLANK_ICE_SNAPS"], f25_file, ln=2, dtypes=[float]
        )
    else:
        msg = f"NWS {NWS} Not yet implemented!"
        logger.error(msg)
        raise Exception(msg)

    return ds

def read_fort221(f221_file, NWS=12, times=[], ds=None):
    if ds != None:
        if "NWS" in ds.attrs.keys():
            NWS = ds.attrs["NWS"]
    else:
        ds = xr.Dataset()

    if NWS in [12, 12012]:
        pressure_data = read_owi_met(f221_file, vals=["press"], times=times)
    else:
        msg = f"NWS {NWS} Not yet implemented!"
        logger.error(msg)
        raise Exception(msg)

    attrs = {"press_" + str(key): val for key, val in pressure_data.attrs.items()}
    pressure_data.attrs = attrs
    return xr.merge([ds, pressure_data], combine_attrs="no_conflicts")

def read_fort222(f222_file, NWS=12, times=[], ds=None):
    if ds != None:
        if "NWS" in ds.attrs.keys():
            NWS = ds.attrs["NWS"]
    else:
        ds = xr.Dataset()

    if NWS in [12, 12012]:
        wind_data = read_owi_met(f222_file, vals=["u_wind", "v_wind"], times=times)
    else:
        msg = f"NWS {NWS} Not yet implemented!"
        logger.error(msg)
        raise Exception(msg)

    attrs = {"wind_" + str(key): val for key, val in wind_data.attrs.items()}
    wind_data.attrs = attrs
    return xr.merge([ds, wind_data], combine_attrs="no_conflicts")

def read_fort225(f225_file, NWS=12, times=[], ds=None):
    if ds != None:
        if "NWS" in ds.attrs.keys():
            NWS = ds.attrs["NWS"]
    else:
        ds = xr.Dataset()

    if NWS in [12, 12012]:
        ice_data = read_owi_met(f225_file, vals=["ice_cov"], times=times)
    else:
        msg = f"NWS {NWS} Not yet implemented!"
        logger.error(msg)
        raise Exception(msg)

    attrs = {"ice_" + str(key): val for key, val in ice_data.attrs.items()}
    ice_data.attrs = attrs
    return xr.merge([ds, ice_data], combine_attrs="no_conflicts")

def read_owi_met(path, vals=["v1"], times=[0]):
    # NWS 12 - Ocean Weather Inc (OWI) met data
    attrs = {}

    # Title line:
    # 10 format (t56,i10,t71,i10)
    # read (20,10) date1,date2
    line = lc.getline(path, 1)
    attrs["source"] = line[0:56]
    attrs["start_ts"] = pd.to_datetime(line[55:66].strip(), format="%Y%m%d%H")
    attrs["end_ts"] = pd.to_datetime(line[70:80].strip(), format="%Y%m%d%H")

    if len(lc.getline(path, 2)) > 79:
        tf = "%Y%m%d%H%M%S"
        ti_idx = 67
    else:
        tf = "%Y%m%d%H"
        ti_idx = 68

    cur_line = 2
    all_data = []
    line = lc.getline(path, cur_line)
    for t in times:
        if line == "":
            break
        # Grid Spec Line:
        # 11 format (t6,i4,t16,i4,t23,f6.0,t32,f6.0,t44,f8.0,t58,f8.0,t69,i10,i2)
        # read (20,11) iLat, iLong, dx, dy, swlat, swlong, lCYMDH, iMin
        grid_spec = re.sub("[^\-0-9=.]", "", line)[1:].split("=")
        ilat = int(grid_spec[0])
        ilon = int(grid_spec[1])
        dx = float(grid_spec[2])
        dy = float(grid_spec[3])
        swlat = float(grid_spec[4])
        swlon = float(grid_spec[5])
        ts = pd.to_datetime(grid_spec[6], format=tf)

        # swlon = float(line[57:65])
        # ts = pd.to_datetime(line[68:len(line)-1], format=tf)

        logger.info(f"Processing data at {ts}")

        data = {}
        line_count = int(ilat * ilon / 8.0)
        remainder = int(ilat * ilon - (line_count * 8))
        for v in vals:
            vs = np.zeros(ilat * ilon)

            with open(path, "r") as f:
                vs[0 : (8 * line_count)] = pd.read_fwf(
                    f, nrows=line_count, skiprows=cur_line, widths=8 * [10], header=None
                ).values.flatten()
            if remainder > 0:
                with open(path, "r") as f:
                    vs[(8 * line_count) :] = pd.read_fwf(
                        f,
                        nrows=1,
                        skiprows=cur_line + line_count,
                        widths=remainder * [10],
                        header=None,
                    ).values.flatten()
                cur_line = cur_line + line_count + 1
            else:
                cur_line = cur_line + line_count

            vs = vs.reshape(1, ilat, ilon)
            data[v] = (["time", "latitude", "longitude"], vs)

        # Convert swlon to positive longitude value
        if swlon < 0:
            swlon = 360 + swlon
        lon = np.arange(start=swlon, stop=(swlon + (ilon * dx)), step=dx)
        # lon = np.where(lon<180.0,lon,lon-360)

        coords = {
            "time": [ts],
            "longitude": lon,
            "latitude": np.arange(start=swlat, stop=(swlat + (ilat * dy)), step=dy),
        }
        all_data.append(xr.Dataset(data, coords=coords))

        # Get next line corresponding to next datapoint, or empty if done
        cur_line += 1
        line = lc.getline(path, cur_line)

    if len(all_data) > 0:
        ret_ds = xr.concat(all_data, "time")
    else:
        ret_ds = xr.Dataset()

    ret_ds.attrs = attrs

    return ret_ds

def write_fort14(ds, f14_file):
    """write_fort14.
  Reads in ADCIRC fort.14 f14_file

  :param f14_file: Path to Python file.
  """
    with open(f14_file, "w") as f14:
        # 1 : AGRID = alpha-numeric grid identification (<=24 characters).
        write_text_line(ds, "AGRID", f14)

        # 2 : NE, NP = number of elements, nodes in horizontal grid
        write_param_line(ds, ["NE", "NP"], f14)

    # 3-NP : NODES
    # for k=1 to NP
    #    JN, X(JN), Y(JN), DP(JN)
    # end k loop
    logger.info("Wriing Node Map.")
    ds[["JN", "X", "Y", "DP"]].to_dataframe().to_csv(
        f14_file, sep=" ", mode="a", header=False
    )

    # (2+NP)-(2+NP+NE) : ELEMENTS
    # for k=1 to NE
    #    JE, NHY, NM(JE,1),NM(JE,2), NM(JE,3)
    # end k loop
    logger.info("Writing Element Map.")
    ds[["JE", "NHEY", "NM_1", "NM_2", "NM_3"]].to_dataframe().to_csv(
        f14_file, sep=" ", mode="a", header=False
    )

    # Elevation specified boundaries
    with open(f14_file, "a") as f14:
        # (3+NP+NE) : NOPE = number of elevation specified boundary forcing segments.
        write_param_line(ds, ["NOPE"], f14)

        # (4+NP+NE) : NETA = total number of elevation specified boundary nodes
        write_param_line(ds, ["NETA"], f14)

    for (bnd_idx, bnd) in ds[["ELEV_BOUNDARY_NODES", "IBTYPEE"]].groupby(
        "ELEV_BOUNDARY"
    ):
        with open(f14_file, "a") as f14:
            # NVDLL(k), IBTYPEE(k) = number of nodes, and boundary type
            write_param_line(
                xr.Dataset(
                    attrs={
                        "NVDLL": bnd["ELEV_BOUNDARY_NODES"].shape[0],
                        "IBTYPEE": bnd["IBTYPEE"].item(0),
                    }
                ),
                ["NVDLL", "IBTYPEE"],
                f14,
            )
        bnd["ELEV_BOUNDARY_NODES"].to_dataframe().to_csv(
            f14_file, sep=" ", mode="a", header=False, index=False
        )

    # Normal flow specified boundaries
    with open(f14_file, "a") as f14:
        # NBOU = number of normal flow (discharge) specified boundary segments
        write_param_line(ds, ["NBOU"], f14)

        # NVEL = total number of normal flow specified boundary nodes
        write_param_line(ds, ["NVEL"], f14)

    for (bnd_idx, bnd) in ds[["NORMAL_BOUNDARY_NODES", "IBTYPE"]].groupby(
        "NORMAL_BOUNDARY"
    ):
        with open(f14_file, "a") as f14:
            # NVELL(k), IBTYPE(k) = number of nodes, and boundary type
            write_param_line(
                xr.Dataset(
                    attrs={
                        "NVELL": bnd["NORMAL_BOUNDARY_NODES"].shape[0],
                        "IBTYPE": bnd["IBTYPE"].item(0),
                    }
                ),
                ["NVELL", "IBTYPE"],
                f14,
            )
        bnd["NORMAL_BOUNDARY_NODES"].to_dataframe().to_csv(
            f14_file, sep=" ", mode="a", header=False, index=False
        )

def write_fort15(ds, f15_file):
    """write_fort15.
    Writes out an ADCIRC fort.15 f15_file

    Args:
        ds (dict) - Dictionary of parameters
        f15_file (str) - output filename
    """

    parser = ParamParser(fort15_instructions)
    # Needed before writing to the file
    remove_symlink(f15_file)
    parser.dump(f15_file, data=ds)

def fix_fort_params(fname, params):
    """Read a file line by line - and make some quick-and-dirty fixes
    """
    params = params.copy()
    with open(fname, "r") as fp:
        lines = fp.readlines()

    for i in range(len(lines)):
        l = lines[i]
        if "!" not in l: continue
        parts = l.split("!")
        value = parts[0]
        comment = "!".join(parts[1:])
        for param, new_value in list(params.items()):
            if param.lower() in comment.lower():
                if new_value is None:
                    # remove line
                    lines[i] = ""
                    del params[param]
                    break
                new_value = str(new_value).ljust(len(value), " ")
                if len(new_value) >= len(value):
                    new_value += " "
                lines[i] = new_value+"!"+comment
                del params[param]
                break

    with open(fname, "w") as fp:
        fp.write("".join(lines))

def fix_all_fort15_params_cmd(run_dir, params):
    cmd_list = []
    for k,v in params.items():
         cmd_list.append(f"s/.*\!.*{k}/{v}    ! {k}/g")
    return f"sed -i '{ ';'.join(cmd_list)}' {run_dir}/PE*/fort.15"

def snatch_fort_params(fname, params):
    res = {}
    with open(fname, "r") as fp:
        for line in fp:
            if "!" not in line: continue
            parts = line.split("!")
            val, comment = parts[0], "!".join(parts[1:])
            for p in params:
                if p in res: continue
                if p in comment:
                    res[p] = val.strip()

    return res

def create_nodal_att(name, units, default_vals, nodal_vals):
    str_vals = [f"v{str(x)}" for x in range(len(default_vals))]
    base_df = (
        pd.DataFrame(
            [[name, units, len(default_vals)] + list(default_vals)],
            columns=["AttrName", "Units", "ValuesPerNode"] + str_vals,
        )
        .set_index("AttrName")
        .to_xarray()
    )
    default_vals = (
        pd.DataFrame(
            [],
            columns=["JN"]
            + ["_".join([name, str(x)]) for x in range(len(default_vals))],
        )
        .set_index("JN")
        .to_xarray()
    )

    return xr.merge([base_df, default_vals])

def add_nodal_attribute(f13, name, units, default_vals, nodal_vals):
    if type(f13) != xr.Dataset:
        f13 = read_fort13(f13)
    if name in f13["AttrName"]:
        raise Exception(f"Error - Nodal Attribute {name} already in f13 configs.")
    new_nodal = create_nodal_att(name, units, default_vals, nodal_vals)

    df = xr.merge([f13, new_nodal], combine_attrs="override")
    df.attrs["NAttr"] = len(df["AttrName"].values)

    return df

def write_fort13(ds, f13_file):

    with open(f13_file, "w") as f13:
        write_param_line(ds, ["AGRID"], f13)

        write_param_line(ds, ["NumOfNodes"], f13)

        write_param_line(ds, ["NAttr"], f13)

        # Write Nodal Attribute info
        for attr in ds["AttrName"].values:
            write_text_line(attr, "", f13)
            write_text_line(str(ds.sel(AttrName=attr)["Units"].item(0)), "", f13)
            write_text_line(
                str(ds.sel(AttrName=attr)["ValuesPerNode"].item(0)), "", f13
            )
            def_vs = [
                "v" + str(x)
                for x in range(int(ds.sel(AttrName=[attr])["ValuesPerNode"].item(0)))
            ]
            def_vals = [
                str(x.item(0)) for x in ds.sel(AttrName=[attr])[def_vs].values()
            ]
            write_text_line(" ".join(def_vals), "", f13)

    # Write non default values
    for attr in ds["AttrName"].values:
        with open(f13_file, "a") as f13:
            write_text_line(attr, "", f13)
            cols = [
                "_".join([attr, str(x)])
                for x in range(int(ds.sel(AttrName=attr)["ValuesPerNode"].item(0)))
            ]
            out_df = ds[cols].dropna("JN").to_dataframe()
            write_text_line(str(out_df.shape[0]), "", f13)
        out_df.to_csv(f13_file, sep=" ", mode="a", header=None)

def process_adcirc_configs(path, filt="fort.*", met_times=[]):
    ds = xr.Dataset()

    # Always read fort.14 and fort.15
    adcirc_files = glob.glob(os.path.join(path, filt))
    for ff in adcirc_files:
        ftype = int(ff.split(".")[-1])
        with timing(f"Reading {ff}") as read_time:
            if ftype == 14:
                logger.info(f"Reading fort.14 file {ff}...")
                ds = read_fort14(ff, ds=ds)
            elif ftype == 15:
                logger.info(f"Reading fort.15 file {ff}...")
                ds = read_fort15(ff, ds=ds)
            elif ftype == 13:
                logger.info(f"Reading fort.13 file {ff}...")
                ds = read_fort13(ff, ds=ds)
            elif ftype == 22:
                logger.info(f"Reading fort.22 file {ff}...")
                ds = read_fort22(ff, ds=ds)
            elif ftype == 24:
                logger.info(f"Reading fort.24 file {ff}...")
                ds = read_fort24(ff, ds=ds)
            elif ftype == 25:
                logger.info(f"Reading fort.25 file {ff}...")
                ds = read_fort25(ff, ds=ds)
            elif ftype == 221:
                logger.info(f"Reading fort.221 file {ff}...")
                ds = read_fort221(ff, ds=ds, times=met_times)
            elif ftype == 222:
                logger.info(f"Reading fort.222 file {ff}...")
                ds = read_fort222(ff, ds=ds, times=met_times)
            elif ftype == 225:
                logger.info(f"Reading fort.225 file {ff}...")
                ds = read_fort225(ff, ds=ds, times=met_times)
            else:
                msg = f"Uncreognized file type = {ff}"
                logger.error(msg)
                raise Exception(msg)
        logger.info(f"Read {ff} successfully! - {read_time()[1]}")

    return ds

#P_CONFIGS = pull_param_configs()

def getlines(fname):
    with open(fname, "r") as fp: return fp.readlines()

def writelines(fname, lines):
    with open_paramfile(fname) as fp: fp.writelines(lines)

def remove_symlink(fname):
    """If a filename is a symlink - remove the symlink.
    """

    if os.path.islink(fname):
        os.unlink(fname)

def open_paramfile(fname):
    """Safely open paramfile for writing - removing a symlink if one exists.

    Often parameter files will be symlinks initially. We often need to modify the local file
    without changing the shared source/template file.
    """

    remove_symlink(fname)
    return open(fname, "w")

def add_swan(inputsdir, start_date, end_date, tstep=1200):
    """Enable SWAN for an ADCIRC inputs directory
    """
    out_fort15 = inputsdir+"/fort.15"
    params = snatch_fort_params(out_fort15, ["WTM", "NWS"])
    wtiminc_parts = params["WTM"].strip().split()
    nws = params["NWS"].strip()
    if len(nws) < 3 or nws[-3] != '3':
        nws = int(nws)
        nws += 300
        if nws > 1000:
            wtiminc_parts.insert(-1, str(tstep))
        else:
            wtiminc_parts.append(str(tstep))
    else:
        if int(nws) > 1000:
            wtiminc_parts[-2] = str(tstep)
        else:
            wtiminc_parts[-1] = str(tstep)

    fix_fort_params(out_fort15, {"WTM": " ".join(wtiminc_parts), "NWS": nws})
    set_swan_control(inputsdir+"/fort.26", start_date, end_date, tstep=tstep)

def set_swan_control(fname, start_date, last_date, tstep=1200):
    """Set dates and timestep in SWAN control file.

    Args:
    fname (str) - input file name - will be overwritten
    start_date (datetime.datetime) - starting date
    last_date (dateimime.datetime - The last date in the forcing data.
    Even if the simulation doesn't go that far, the
    COMPUTE line in fort.26 needs to use the last date from the fort.22 file.
    """

    lines = getlines(fname)
    # support only hours for now
    fmt = "%Y%m%d.%H0000"
    start_str = start_date.strftime(fmt)
    last_str = last_date.strftime(fmt)
    new_lines = []
    wtiminc = start_date.strftime("%Y %m %d %H 1 0.9 1 ") + str(tstep)
    for i in range(len(lines)):
        l = lines[i]
        if "INIT HOTSTART" in l+lines[i-1]: continue
        if " SEC " in l:
            parts = l.split(" ")
            ind = parts.index("SEC")
            parts[ind-1] = str(tstep)
            if "COMPUTE" in l:
                parts[ind-2], parts[ind+1] = start_str, last_str
            else:
                parts[ind-2], parts[ind+1] = start_str, last_str
            new_lines.append(" ".join(parts)+"\n")
        elif "WTIMINC" in l:
            new_lines.append("'WTIMINC Line in ADCIRC fort.15 " + wtiminc +"'\n")
        else:
            new_lines.append(l)
    writelines(fname, new_lines)
    return wtiminc

def compute_tides(rnday, start_date, tide_fac_path):
    """Compute the tidal node factors and degrees

    rnday -- days to run simulation
    start_date -- date of simulation start
    tide_fac_path -- path to tide_fac executable
    """

    hours = start_date.hour
    days = start_date.day
    month = start_date.month
    year = start_date.year
    outfile = "tide_fac.out"
    if os.path.exists(outfile):
        os.system(f"rm {outfile}")
    subprocess.run(f"printf '{rnday}\\n{hours} {days} {month} {year}\\n' | {tide_fac_path}",
            shell=True, check=True)
    # read outfile
    seen_name = False
    tides = {}
    with open(outfile) as fp:
        for line in fp:
            parts = line.strip().split()
            if not len(parts): continue
            if parts[0].lower() == "name" and not seen_name:
                seen_name = True
                continue
            if len(parts) == 3 and seen_name:
                tides[parts[0]] = parts[1:]

    return tides

def set_tides(fort15, tides):
    with open(fort15) as fp:
        lines = fp.readlines()

    for i in range(len(lines)-1):
        l = lines[i].strip().split()[0]
        if l in tides:
            factor, deg = tides[l]
            next_line = lines[i+1]
            parts = next_line.split("!")
            data = parts[0].split()
            if len(data) < 3:
                continue
            data[-2], data[-1] = factor, deg
            stripped = parts[0].rstrip()
            trailing_whitespace = parts[0][len(stripped):]
            parts[0] = " ".join(data) + trailing_whitespace

            lines[i+1] = "!".join(parts)

    with open(fort15, "w") as fp:
        fp.write("".join(lines))

def set_run_dates(inputsdir, start_date, end_date,
        tide_fac_path=None):
    """Given an ADCIRC template, set the run dates and update the tides.

    This function will update BASE_DATE, RNDY, and will set the swan control files appropriately.
    """

    start, end = pd.to_datetime(start_date), pd.to_datetime(end_date)
    diff = end-start
    rnday = diff.days + diff.seconds / 86400
    out_fort15 = f"{inputsdir}/fort.15"
    fix_fort_params(out_fort15, {
            "BASE_DATE": start.strftime("%Y-%m-%d 00:00:00 UTC"),
            "RND": rnday
        }
    )

    if tide_fac_path is not None:
        tides = compute_tides(rnday, start, tide_fac_path)
        set_tides(out_fort15, tides)

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)


# 6자리의 숫자를 입력 받고
# 연속되는 숫자 2 3 4 (run 이라고 함)
# 같은 숫자의 연속 7 7 7 (triplete 라고 함)
# 위와 같은 조건이 만족할 때 Baby-gin 이라고 한다.

# 완전 검색 방법으로 해결
import itertools

list1 = ['1', '2', '3', '7', '7', '7']

permutayions_list = list(map(''.join, itertools.permutations(list1, len(list1))))

for i in permutayions_list:
   if i[3] is i[4] and [5]:
       if int(i[0]) + 1 is int(i[1]) and int(i[1]) + 1 is int(i[2]):
            print('Baby-gin')
            break

#탐욕법으로 해결
#1부터 9까지 빈 리스트에 숫자를 카운트하고
#연속된 (run)이 존재하면 리스트 - 1 해준다
#남은 리스트 요소중 하나가 3 이라면 Baby_gin이 완성된다.

list2 = ['2','3','4','8','8','8']
temp = []
for _ in range(9):
    temp.append(0)

for k in list2:
    for i in range(0, 9):
        if int(k) is i:
            temp[i-1] += 1

cnt = 0
for t in range(1, 8):
    if temp[t] > 0 and temp[t+1] > 0 and temp[t-1] > 0:
        #print('run')

        for j in range(t - 1, t + 2):
            temp[j] = temp[j] - 1
        for j2 in temp:
            if j2 is 3:
                #print('triplete')
                print('Baby_gin')


#!/usr/env/python3
# -*- coding: utf-8 -*-
"""Demo csci4831final code."""
import os
import logging
import cv2
import numpy as np
import matplotlib.pyplot as plt

logging.basicConfig(
    level=logging.INFO,
    format="(%(levelname)s): %(asctime)s --- %(message)s",
)

import csci4831final as csf

def demo(image: str, background: str, result_dir: str) -> None:
    """
    Perform demo of csci4831final code.

    Does the following in order:
    1. Craft a true foreground mask of image.
    2. Use mini-batch k-means with identity, grayscale and gaussian
       transforms to get predicted foreground mask.
    3. Use matplotlib to create result graph.
    4. Save results to result_dir.

    Parameters
    ----------
    image: str
        Path to image to process.
    background: str
        Path to virtual background image.
    result_dir: str
        Path to save results to.
    """

    if os.path.exists("all_results.csv"):
        os.remove("all_results.csv")
    if os.path.exists("avg_results.csv"):
        os.remove("avg_results.csv")
    for file in os.listdir(result_dir):
        if not file.startswith("."):
            os.remove(os.path.join(result_dir, file))

    logging.info("Starting...")
    logging.info("Reading images...")
    image_data = cv2.imread(image)
    background_data = cv2.imread(background)
    logging.info("Showing test image...")
    cv2.imshow("Test Image", image_data)
    cv2.imshow("Background Image", background_data)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    logging.info("Getting true mask using grabcut...")
    true_mask = csf.get_points.get_true_mask(image_data)
    logging.info("Got true mask...")

    logging.info("Testing mini-batch KMeans with ID, GS, and 51GB...")
    tests = csf.main.make_tests(
        [
            (csf.clusters.minibatch_kmeans, "MBK")
        ],
        [
            (lambda i: i, "ID"),
            (lambda i: cv2.cvtColor(i, cv2.COLOR_BGR2GRAY), "GS"),
            (lambda i: cv2.GaussianBlur(i, (5, 5), 1), "51GB"),
        ]
    )
    pi = csf.main.PeopleImage(
        filename=os.path.basename(image),
        path=image,
        mask_path="",
        data=image_data,
        mask_data=true_mask
    )
    for test in tests:
        logging.info(
            f"Running {test.model_name} with transform {test.transform_name}"
        )
        csf.main.do_test(test, [pi], result_dir)
        logging.info(f"Time taken: {test.avg_time}")
        logging.info(f"Accuracy: {test.acc}")

    logging.info("Showing Results...")
    fig = plt.figure()
    axes = list()
    rows = 3
    cols = 2
    i = 1
    for prediction in os.listdir(result_dir):
        if prediction.startswith("."):
            continue
        logging.info(f"Loading {prediction}...")
        filename, model_name, trans_name, acc, run_time = prediction.split("_")
        pred_data = np.float32(cv2.imread(
            os.path.join(result_dir, prediction), cv2.IMREAD_COLOR
        ))
        virt_data = np.float32(
            csf.vbg.replace_background(pred_data, background_data)
        )

        pred_data = np.int32(cv2.cvtColor(pred_data, cv2.COLOR_BGR2RGB))
        virt_data = np.int32(cv2.cvtColor(virt_data, cv2.COLOR_BGR2RGB))

        axes.append(fig.add_subplot(rows, cols, i))
        axes[-1].set_title(f"Prediction ({trans_name})")
        plt.imshow(np.int32(pred_data))

        axes.append(fig.add_subplot(rows, cols, i + 1))
        plt.imshow(np.int32(virt_data))

        i += 2

    fig.tight_layout()
    plt.show()

    return None

if __name__ == "__main__":
    demo(
        os.path.abspath("./image.jpg"),
        os.path.abspath("./background.jpg"),
        os.path.abspath("./results")
    )


import torch

from ....target import cached_generators, metric
from ..meta import Network

class fixed_size(metric):
  def __init__(
    self, size, n_iterations='adaptive'
  ):
    """
    :param size: size of the data for training (and validation) datasets
    :param n_iterations: either:
      - an integer - train for `n_iterations` iterations;
      - 'convergence' - train until convergence;
      - 'adaptive' - the same as 'convergence', but with early stop due to
        high train/validation loss difference. Works only if `Network` has `stop_diff` argument set.
    """
    super(fixed_size, self).__init__()
    self.size = size
    self.n_iterations = n_iterations

  def __call__(self, clf : Network, gen_pos, gen_neg, gen_pos_val=None, gen_neg_val=None, budget=None):
    gen_pos, gen_pos_val = cached_generators(gen_pos, gen_pos_val)
    gen_neg, gen_neg_val = cached_generators(gen_neg, gen_neg_val)

    X_pos = torch.tensor(
      gen_pos.samples(self.size), dtype=torch.float32,
      device=clf.device, requires_grad=False
    )
    X_neg = torch.tensor(
      gen_neg.samples(self.size), dtype=torch.float32,
      device=clf.device, requires_grad=False
    )

    if isinstance(self.n_iterations, int):
      ce = clf.fixed_fit(X_pos, X_neg, self.n_iterations)
      return self.size, ce

    elif self.n_iterations == 'convergence':
      ce = clf.adaptive_fit(X_pos, X_neg)
      return self.size, ce

    elif self.n_iterations == 'adaptive':
      X_pos_val = torch.tensor(
        gen_pos_val.samples(self.size), dtype=torch.float32,
        device=clf.device, requires_grad=False
      )
      X_neg_val = torch.tensor(
        gen_neg_val.samples(self.size), dtype=torch.float32,
        device=clf.device, requires_grad=False
      )

      ce, ce_val = clf.adaptive_fit(X_pos, X_neg, X_pos_val, X_neg_val)
      if ce is not None:
        return self.size, (ce + ce_val) / 2
      else:
        return self.size, None


# -*- coding: utf-8 -*-
"""
collective.pullrequestreview

Licensed under the GPL license, see LICENCE.txt for more details.
"""
import os
from os.path import exists
from shutil import rmtree
import subprocess
from tempfile import mkdtemp, template

DEV_NULL = open('/dev/null', 'w')

class GitRepository(object):

    def __init__(self, name, path):
        self.name = name
        self.path = path

    def merge(self, repository_url, branch='master'):
        os.chdir(self.path)
        subprocess.check_call(['git', 'remote', 'add', 'head', repository_url], stdout=DEV_NULL, stderr=DEV_NULL)
        subprocess.check_call(['git', 'fetch', 'head'], stdout=DEV_NULL, stderr=DEV_NULL)
        subprocess.check_call(['git', 'merge', 'head/%s' % branch], stdout=DEV_NULL, stderr=DEV_NULL)

class GitClone(object):

    def __init__(self, name, url, suffix="", prefix=template, dir=None):
        self.base_path = mkdtemp(suffix, prefix, dir)
        self.name = name
        self.path = os.path.join(self.base_path, self.name)
        self.url = url

    def __enter__(self):
        os.chdir(self.base_path)
        subprocess.check_call(['git', 'clone', self.url], stdout=DEV_NULL, stderr=DEV_NULL)
        return GitRepository(self.name, self.path)

    def cleanup(self):
        if exists(self.base_path):
            rmtree(self.base_path)

    def __exit__(self, exc, value, tb):
        self.cleanup()


from django.urls import path,include
from menu.views import MenuCategoryListView,MenuListView,ItemListView
app_name = 'menu'

urlpatterns = [
    path('category',MenuCategoryListView.as_view()),
    path('category/<category_id>/menu',MenuListView.as_view()),
    path('items',ItemListView.as_view())
]


#!/usr/bin/env python

# import agents

import numpy  as np
import tensorflow as tf

from keras import backend as K

from huber import huber_loss_function, mean_squared_loss

#
# [Proximal Policy Optimization Algorithms,2017] (../../papers/ppo.pdf)
# improved
#

def get_ppo_actor_loss_clipped_obj(advantage_input, old_prediction_input, clip_epsilon=0.2, beta=0.01):
    """
        Make loss function for Proximal Policy optimization with clipped objective

        advantage = rewards - values

        current policy pi(at|st)
        second policy pi_theta(at|st)

        ratio between new and old policy

        according to mentioned paper, the clipping for surrogate loss is better then KL penalty.
        we implement only clipping.

        we get the minimum between standard surrogate loss and an epsilon clipped surrogate loss

        then we add entropy to the policy in order to improve exploration
        adding the entropy of the policy pi to the objective function improved exploration by discouraging premature
        convergence to suboptimal deterministic policies.
        This technique was originally proposed by (Williams & Peng, 1991),
        entropy_reg = beta * Gradient theta' ( H(pi(st;theta')) )
        H is entropy
        entropy  = pi * K.log(pi + epsilon)

    """

    def __actor_loss(y_true, y_pred):
        epsilon = 1e-10
        # epsilon = K.epsilon()  # 1e-7

        # p = y_pred

        # probability = K.sum(y_true * p, axis=1)

        policy = y_true * y_pred
        policy_old = y_true * old_prediction_input

        # add epsilon to avoid dividing by zero
        ratio = policy / (policy_old + epsilon)
        # K.clip may rise an error of unclear type - convert to tensor
        ratio = tf.convert_to_tensor(ratio)

        # clip ratio
        ratio_clipped = K.clip(
            ratio,
            min_value=1 - clip_epsilon,
            max_value=1 + clip_epsilon)

        # minimum between the standard surrogate loss and an epsilon clipped surrogate loss
        surrogate = K.minimum(ratio * advantage_input, ratio_clipped * advantage_input)

        # adding the entropy of the policy pi to the objective function improved exploration by discouraging premature
        # convergence to suboptimal deterministic policies.
        # This technique was originally proposed by (Williams & Peng, 1991),
        # entropy_reg = beta * Gradient theta' ( H(pi(st;theta')) )
        # H is entropy
        # entropy  = p * K.log(p + epsilon)
        entropy_reg = beta * K.sum(policy * K.log(policy + epsilon))

        policy_loss = -K.mean(surrogate)

        # input for the back propagation
        actor_loss = policy_loss + entropy_reg

        # alternative
        # entropy = beta *  policy * K.log(policy + epsilon)
        # actor_loss = -K.mean(surrogate + entropy)
        return actor_loss

    return __actor_loss

#
# [Proximal Policy Optimization Algorithms,2017] (../../papers/ppo.pdf)
# adapted to continuous control
#
# the Gaussian policy is described in paper
# [The Beta Policy for Continuous Control Reinforcement Learning, 2017](../../papers/thesis_chou.pdf)
#

def get_ppo_actor_loss_clipped_obj_continuous(advantage_input, old_prediction_input, clip_epsilon=0.2, sigma=1.0):
    '''
        Make loss function for Proximal Policy optimization with clipped objective

        advantage = rewards - values

        current policy pi(at|st)
        second policy pi_theta(at|st)

        pi_theta(a|s) = exp ( -square(a - mu) / (2 * square(sigma) ) )  /
                                                        ( sqrt(2 * np.pi ) * sigma )
        where the mean mu = mu_theta(s) (y_pred)
        and the standard deviation sigma = sigma_theta(s) is a noise
        a is y_true

        ratio between new and old policy

        according to mentioned paper, the clipping for surrogate loss is better then KL penalty.
        we implement only clipping.

        we get the minimum between standard surrogate loss and an epsilon clipped surrogate loss

    '''

    def __actor_loss(y_true, y_pred):
        epsilon = 1e-10
        # epsilon = K.epsilon()  # 1e-7

        # p = y_pred

        # probability = K.sum(y_true * p, axis=1)

        # print("get_ppo_actor_loss_clipped_obj_continuous")
        # print(type(y_true))
        # print(y_true.dtype)
        # print(y_true.get_shape())
        # print(type(y_pred))
        # print(y_pred.dtype)

        squared_noise = K.square(sigma)
        denominator = K.sqrt(2 * np.pi * squared_noise)

        # print(squared_noise.dtype)
        # print(denominator.dtype)

        if K.is_tensor(y_true):
            policy = K.exp(- K.square(y_true - y_pred) / (2 * squared_noise)) / denominator
            policy_old = K.exp(- K.square(y_true - old_prediction_input) / (2 * squared_noise)) / denominator
        else:
            a_mu = tf.convert_to_tensor(y_true - y_pred, dtype=tf.float32)
            a_mu_old = tf.convert_to_tensor(y_true - old_prediction_input, tf.float32)
            policy = K.exp(- K.square(a_mu) / (2 * squared_noise)) / denominator
            policy_old = K.exp(- K.square(a_mu_old) / (2 * squared_noise)) / denominator

        # add epsilon to avoid dividing by zero
        ratio = policy / (policy_old + epsilon)

        # K.clip may rise an error of unclear type - convert to tensor
        ratio = tf.convert_to_tensor(ratio)

        # clip ratio
        ratio_clipped = K.clip(
            ratio,
            min_value=1 - clip_epsilon,
            max_value=1 + clip_epsilon)

        # minimum between the standard surrogate loss and an epsilon clipped surrogate loss
        surrogate = K.minimum(ratio * advantage_input, ratio_clipped * advantage_input)

        policy_loss = -K.mean(surrogate)

        # do not add entropy

        # input for the back propagation
        actor_loss = policy_loss

        return actor_loss

    return __actor_loss

def get_ppo_critic_loss(clip_value=np.inf):
    ''' mean of squared errors '''
    # def __critic_loss(y_true, y_pred):
    #    return K.mean(K.square(y_true - y_pred), axis=-1)
    # return __critic_loss
    return huber_loss_function(clip_value)

def test():
    shape = (6, 7)
    y_a = np.random.random(shape)
    y_b = np.random.random(shape)

    # advantage_input = Input(shape=(1,))

    # a_i = np.random.random( (1,6))
    a_i = np.random.random((1,))
    # a_i = 0.
    op_i = np.random.random(shape)

    loss = get_ppo_actor_loss_clipped_obj(a_i, op_i, clip_epsilon=0.2, beta=0.01)

    print("")
    print("================")
    print("get_ppo_actor_loss_clipped_obj")
    print("================")
    out1 = K.eval(loss(K.variable(y_a), K.variable(y_b)))
    print(out1)
    print("================")
    out2 = K.eval(loss(y_a, y_b))
    print(out2)
    print("================")

    loss = get_ppo_actor_loss_clipped_obj_continuous(a_i, op_i, clip_epsilon=0.2, sigma=1.0)

    print("")
    print("================")
    print("get_ppo_actor_loss_clipped_obj_continuous")
    print("================")
    out1 = K.eval(loss(tf.convert_to_tensor(y_a, dtype=tf.float32), tf.convert_to_tensor(y_b, dtype=tf.float32)))
    print(out1)
    print("================")
    out2 = K.eval(loss(y_a, y_b))
    print(out2)
    print("================")

    loss = get_ppo_critic_loss(np.inf)

    print("")
    print("================")
    print("get_ppo_critic_loss (inf)")
    print("================")
    out1 = K.eval(loss(K.variable(y_a), K.variable(y_b)))
    print(out1)
    print("================")
    out2 = K.eval(loss(y_a, y_b))
    print(out2)
    print("================")

    loss = get_ppo_critic_loss(1.0)
    print("")
    print("================")
    print("get_ppo_critic_loss (1.0)")
    print("================")
    out1 = K.eval(loss(K.variable(y_a), K.variable(y_b)))
    print(out1)
    print("================")
    out2 = K.eval(loss(y_a, y_b))
    print(out2)
    print("================")

if __name__ == "__main__":
    test()

    print("passed")
    input("Enter to exit")


import json
import csv

with open('covid_cases.json','r') as json_file:
    Ourjson = json.load(json_file)

Covid_Data = Ourjson['records']
Data_File = open('Data_File.csv','w')
csv_w = csv.writer(Data_File)

#Count
c = 0
for r in Covid_Data:
    if c == 0:
        header = r.keys()
        csv_w.writerow(header)
        c += 1
    csv_w.writerow(r.values())
Data_File.close()


'''
Created on 2019. 1. 9.

@author: gdj4
이미지 데이터 학습하기
'''

from sklearn import model_selection,svm,metrics

def load_csv(fname):
    labels = [] # 숫자값
    images = [] # 이미지 이진파일
    with open(fname,"r") as f:
        for line in f:
            cols = line.split(",")
            if len(cols)<2 : continue # ,를 이용한 단어수가 1이하인 경우 다음 라인을 읽기
            labels.append(int(cols.pop(0))) # 정답. 숫자값
            vals = list(map(lambda n : int(n)/256,cols)) # cols : 이미지정보 데이터만 존재
            images.append(vals)
        return {"labels":labels,"images":images}
data = load_csv("./mnist/train.csv")
test = load_csv("./mnist/t10k.csv")

clf = svm.SVC()
clf.fit(data["images"],data["labels"])
pre = clf.predict(test["images"])
ac_score = metrics.accuracy_score(test["labels"],pre)
cl_report = metrics.classification_report(test["labels"],pre)
print("정답률 = ",ac_score)
print("리포트 = ")
print(cl_report)


import pysam as ps
import os

def Read_bed(bed):
	if not os.path.isfile(bed):
		print('Bedfile does not exist at location provided, please check (tried "{}")'.format(bed))
		exit(2)
	print("Loading bed file: {} ...".format(bed))
	bed_f = open(bed)
	CNV_bed=[]
	for line in bed_f:
		line=line.strip("\n")
		line_list=line.split("\t")
		CNV_bed.append(line_list)
	bed_f.close()
	return CNV_bed

def Read_bas(bas):
	if not os.path.isfile(bas):
		print('Bedfile does not exist at location provided, please check (tried "{}")'.format(bas))
		exit(2)
	print("Loading bas file: {} ...".format(bas))
	bas_f = open(bas)
	RG_bas={}
	for line in bas_f:
		line=line.strip("\n")
		line_list=line.split("\t")
		RG_bas[line_list[6]]=line_list[15]+"\t"+line_list[16]+"\t"+line_list[-1]
	bas_f.close()
	return RG_bas

def Read_bam(bam):
	print("Loading bam file: {} ...".format(bam))
	bamfile = ps.AlignmentFile(bam, 'rb')
	try:
		bamfile.check_index()
		print('Index file found - {}'.format(bam + '.bai'))
	except ValueError:
		print('Index file not found (should be named "{}.bai" and located in the same directory)'.format(bam))
	return bamfile


from devices import udid
from multi_appiuim import appium_start
from check_port import check_port, release_port
from common.desired_caps import appium_desired
from time import sleep
import multiprocessing

def start_appium_action(host, port):
    if check_port(host, port):
        appium_start(host, port)
        # sleep(2)
        # return True
        return False
    else:
        print('appium %s start fail' % port)
        # return False
        return True

def start_devices_action(udid, port):
    host = '127.0.0.1'
    if start_appium_action(host, port):
        appium_desired(udid, port)
    else:
        release_port(port)

def appium_start_sync():
    print('=====appium_start_sync=====')

    appium_process = []

    for i in range(2):
        host = '127.0.0.1'
        port = 4723 + 2 * i

        appium = multiprocessing.Process(target=start_appium_action, args=(host, port))
        appium_process.append(appium)

    for appium in appium_process:
        appium.start()
    for appium in appium_process:
        appium.join()

def devices_star_sync():
    print('======devices_star_sync===')

    desired_process = []
    devices_list = udid()

    for i in range(len(devices_list)):
        port = 4723 + 2 * i
        desired = multiprocessing.Process(target=start_devices_action, args=(devices_list[i], port))
        desired_process.append(desired)

    for desired in desired_process:
        desired.start()
    for desired in desired_process:
        desired.join()

if __name__ == '__main__':
    # appium_start_sync()
    devices_star_sync()


import sys
import numpy as np
from sklearn import svm
from sklearn.naive_bayes import GaussianNB
from sklearn import tree

def read_dataset(filename, n_features):
	f = open(filename, 'r')
	line = f.readline()
	token = line.split(",")
	X = np.zeros((n_features))
	for i in range(n_features):
		X[i] = float(token[6 + i])
	Y = np.array([int(token[0])])

	line = f.readline()
	while(line):
		token = line.split(",")
		X1 = np.zeros((n_features))
		for i in range(n_features):
			X1[i] = float(token[6 + i])
		Y1 = np.array([int(token[0])])

		X = np.append(X, X1, axis = 0)
		Y = np.append(Y, Y1, axis = 0)
		line = f.readline()

	f.close()
	X = np.reshape(X, (-1, n_features))
	Y = np.reshape(Y, (-1, 1))
	num = np.size(Y)

	return num, X, Y
# end of read_dataset()

def calculate(num, Y, result):
	TP = 0
	TN = 0
	FP = 0
	FN = 0

	for i in range(num):
		if(Y[i] == 1):	# bot
			if(result[i] == 1):
				TP += 1
			else:
				FN += 1
		else:			# normal
			if(result[i] == 0):
				TN += 1
			else:
				FP += 1

	return TP, TN, FP, FN
# end of calculate()

def main():
	if(len(sys.argv) < 3):
		print("Usage: python3 classifier.py cmd training_set n_features testing_set ..., cmd = SVM, NB, DT\n")
		exit(1)

	# Select classifier algorithm
	if(sys.argv[1] == "SVM"):
		clf = svm.SVC(kernel='rbf')
	elif(sys.argv[1] == "NB"):
		clf = GaussianNB()
	elif(sys.argv[1] == "DT"):
		clf = tree.DecisionTreeClassifier()
	else:
		print("Usage: python3 classifier.py cmd training_set n_features testing_set ..., cmd = SVM, NB, DT\n")
		exit(1)

	n_features = int(sys.argv[3])

	# read dataset
	num, X, Y = read_dataset(sys.argv[2], n_features)

	# training
	clf.fit(X, Y)

	# testing
	result = clf.predict(X)

	TP, TN, FP, FN = calculate(num, Y, result)

	f_out = open("out-" + sys.argv[1] + "-" + str(n_features) + ".csv", 'a')
	#f_out.write(sys.argv[1] + "\n")
	#f_out.write("ID, TP, TN, FP, FN, TPR, FPR, ACC\n")
	#string = sys.argv[2] + "," + str(TP) + "," + str(TN) + "," + str(FP) + "," + str(FN) + "," +\
	#		str(TP/(TP+FN)) + "," + str(FP/(FP+TN)) + "," + str((TP+TN)/(TP + TN + FP + FN)) + "\n"
	#f_out.write(string)

	for i in range(4, len(sys.argv)):
		t_num, t_X, t_Y = read_dataset(sys.argv[i], n_features)
		t_result = clf.predict(t_X)

		# write the classification result
		res_fp = open("resO-" + sys.argv[i] , 'w')
		res_num = np.size(t_result)
		for j in range(res_num):
			res_fp.write(str(t_result[j]) + "\n")
		res_fp.close()

		TP, TN, FP, FN  = calculate(t_num, t_Y, t_result)
		string = sys.argv[i] + "," + str(TP) + "," + str(TN) + "," + str(FP) + "," + str(FN) +  "," +\
			str(TP/(TP+FN)) + "," + str(FP/(FP+TN)) + "," + str((TP+TN)/(TP + TN + FP + FN)) + "\n"
		f_out.write(string)

	f_out.close()

# end of main()

if __name__ == '__main__':
	main()


#!/usr/bin/env python3
# Copyright 2017-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the license found in the
# LICENSE file in the root directory of this source tree.
"""Interactive mode for the tfidf DrQA retriever module."""

import argparse
import code
import prettytable
import logging
from drqa import retriever
import pandas as pd

logger = logging.getLogger()
logger.setLevel(logging.INFO)
fmt = logging.Formatter('%(asctime)s: [ %(message)s ]', '%m/%d/%Y %I:%M:%S %p')
console = logging.StreamHandler()
console.setFormatter(fmt)
logger.addHandler(console)

parser = argparse.ArgumentParser()
parser.add_argument('--model', type=str, default=None)
parser.add_argument('--csv', type=str, default=None)
parser.add_argument('--adaptive-model', type=str, default=None)
args = parser.parse_args()

logger.info('Initializing ranker...')
ranker = retriever.get_class('tfidf')(tfidf_path=args.model, adaptive_model_path=args.adaptive_model)

# Loading questions
if args.csv:
    df = pd.read_csv(args.csv)
    df = df[df["Full_Text"].notna()]
    df = df.reset_index()

# ------------------------------------------------------------------------------
# Drop in to interactive
# ------------------------------------------------------------------------------

def process(query, k=1):
    doc_names, doc_scores = ranker.closest_docs(query, k)
    table = prettytable.PrettyTable(
        ['Rank', 'Doc Id', 'Doc Score']
    )
    for i in range(len(doc_names)):
        table.add_row([i + 1, doc_names[i], '%.5g' % doc_scores[i]])
    print(table)

def calculate_top_n_ratio(top_n=3):
    nb_included_in_top_n = 0
    positions_sum = 0
    nb_documents_sum = 0

    for i in df.index:
        question_query = df["Question"][i]
        pmid_query = str(df["Document_ID"][i])

        doc_names, doc_scores = ranker.closest_docs(question_query, top_n)
        nb_documents_sum += len(doc_names)

        for j in range(len(doc_names)):
            pmid_result = doc_names[j]
            if pmid_result == pmid_query:
                nb_included_in_top_n += 1
                positions_sum += (j + 1)

    return (nb_included_in_top_n, nb_included_in_top_n / df.shape[0],
            positions_sum / nb_included_in_top_n, nb_documents_sum / df.shape[0])

banner = """
Interactive TF-IDF DrQA Retriever
>> process(question, k=1)
>> usage()
"""

def usage():
    print(banner)

code.interact(banner=banner, local=locals())


#pylint:skip-file
import os
import cv2
import numpy as np

real=cv2.imread('./real.png',0)
sim=cv2.imread('./simulation.png',0)
real=np.dot(real,0.75)
cv2.imwrite('./reduced_real.png',real)
real=np.asarray(real)
real=np.expand_dims(np.expand_dims(real,axis=0),axis=1)
print ('real:',real.shape)
sim=np.asarray(sim)
sim=np.expand_dims(np.expand_dims(sim,axis=0),axis=1)
print ('sim:',sim.shape)
mean=np.mean(real)
std=np.std(real)
print ('mean:',mean,'std0:',std)


from flask import Flask, request, render_template, redirect, flash
from random import choice, sample
import requests
import json
import os

app = Flask(__name__)
app.secret_key = "SHHHHH ITS A SECRETTTTT."

# We will use os.environ to get at the secret URL as an environmental variable
#
# Note: you must run `source secrets.sh` before running this file
# to make sure these environmental variables are set.

#######################################################################

@app.route('/')
def index():
	return render_template("index.html")

@app.route('/submit',  methods=['POST'])
def submit_json_to_webhook():
	main_text = request.form["**"]
	# moar_text = grab the information coming from your form element named 'moar-text'
	# main_text += ("\n" + moar_text)

	# Same as above, grab the info coming from your title, text, and color form elements.
	# and put fill in the skeleton of the attachemnts dictionary below.
	# title_1 =
	# text_1 =
	# color_1 = editing for testing purpose

	#Build the JSON to send
	payload = {
		'text' : main_text,
		# 'attachments' : [
		# 	{
				# "color" :
		# 	},
		# ]
	}

	# Your secret URL sourced in from secrets.sh
	url = os.environ['WEBHOOK_URL']

	# Send a JSONified version of your payload to the URL Slack provides
	r = requests.post(url, data=json.dumps(payload))
	status_code = r.status_code

	# Check the status code of the respond you receive from Slack.
	# If it's an error, flash a message about it at the bottom of the page.
	if status_code == 200:
		flash('You did it!')
		return redirect("/")
	else:
		flash('Oh no, something went wrong. You are getting a %s  status code error.' % (status_code))

	return redirect("/")

#######################################################################

if __name__ == "__main__":
    app.run(debug=True)


import time
from appium import  webdriver
from appium.webdriver.common.touch_action import TouchAction
#配置基本信息

desired_caps = dict()
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '8.1.0'
desired_caps['deviceName'] = '6TV44HNV5HAYVWZ9'
#包名/界面名
# desired_caps['appPackage'] = 'com.jkc.mitube'
# desired_caps['appActivity'] = 'com.mitac.mitube.SplashActivity'
desired_caps['appPackage'] = 'com.android.contacts'
desired_caps['appActivity'] = '.DialtactsContactsEntryActivity'
desired_caps['noReset'] = True  #不清空缓存数据
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True

#连接appium服务器
dirver = webdriver.Remote('http://localhost:4723/wd/hub' , desired_caps)

time.sleep(3)
'''
模拟手指一直按下，模拟手指抬起。可以用来组合成轻敲或长按的操作
除了按坐标，也能按元素

'''
#---按下和抬起
#两次按下不会进去，这是正常的
# TouchAction(dirver).press(x=270 ,y=1400).perform()
# time.sleep(2)
# TouchAction(dirver).press(x=270 ,y=1400).perform()

# TouchAction(dirver).press(x=270 ,y=1400).perform()
# time.sleep(2)
# TouchAction(dirver).press(x=450 ,y=1400).release().perform()

#----等待操作 单位ms
TouchAction(dirver).press(x=300 ,y=560).wait(2000).release().perform()
time.sleep(2)
TouchAction(dirver).tap(x=300 ,y=560).perform()

time.sleep(3)
dirver.quit()


# python capture_training.py --name Gena --training faces/ --N 20 0
#
# spacebar: captures a picture.  You then have 5s to view the picture and
#           decide if you want to keep it.
# s: will save the picture during the 5s window.
# a (or any non-q, non-s key): will end the 5s preview period.
# q: will quit the program
#

if __name__=='__main__':
    import argparse
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--name', help='name of person', required=True)
    arg_parser.add_argument('--face',
                            default='haarcascade_frontalface_default.xml',
                            help='classifier desciption file')
    arg_parser.add_argument('--training', help='images for training',
                            required=True)
    arg_parser.add_argument('--N', default=10, type=int,
                            help='number of images to capture before complete')
    arg_parser.add_argument('device', default=0, type=int,
                            help='which video device to use')
    args = arg_parser.parse_args()

    import cv2

    faceCascade = cv2.CascadeClassifier(args.face)
    webcam = cv2.VideoCapture(args.device)

    images = []
    go=True
    while go and len(images)<args.N:
        if not webcam.isOpened():
            webcam.open(args.device)

        ret, frame = webcam.read()

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = faceCascade.detectMultiScale(
            gray, scaleFactor=1.3, minNeighbors=5,
            minSize=(frame.shape[1]//10, frame.shape[0]//10))

        for (x,y,w,h) in faces:
            cv2.rectangle(frame, (x,y), (x+w,y+h), (0,255,0), 2)

        cv2.imshow('snap', frame)

        k = cv2.waitKey(1) & 0xFF
        if k == ord('q'):
            go=False
        if k == 32: #spacebar
            if len(faces) == 1:
                webcam.release()
                k = cv2.waitKey(5*1000) & 0xFF
                if k == ord('s'):
                    _face = gray[y:y+h, x:x+h]
                    _face = cv2.resize(_face, (70,70))
                    images.append(_face)
                elif k == ord('q'):
                    go = False

    cv2.destroyAllWindows()

    import os
    tdir = os.path.join(args.training, args.name)
    os.makedirs(tdir, exist_ok=True)
    for i,_face in enumerate(images):
        cv2.imwrite(os.path.join(tdir,'{}.pgm'.format(i)), _face)


import re
from multiprocessing import Process

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import learning_curve
from sklearn.model_selection import train_test_split
from sklearn.model_selection import validation_curve
from sklearn.pipeline import Pipeline

def preprocessor(text):
    text = re.sub('<[^>]*>', '', text)
    emoticons = re.findall('(?::|;|=)(?:-)?(?:\)|\(|D|P)', text)
    text = re.sub('[\W]+', ' ', text.lower()) + \
           ' '.join(emoticons).replace('-', '')
    return text

def tokenizer(text):
    return text.split()

def learning(lr_tfidf, X_train, y_train):
    train_sizes, train_scores, test_scores = \
        learning_curve(estimator=lr_tfidf,
                       X=X_train,
                       y=y_train,
                       train_sizes=np.linspace(0.1, 1.0, 10),
                       cv=5,
                       n_jobs=1)

    train_mean = np.mean(train_scores, axis=1)
    train_std = np.std(train_scores, axis=1)
    test_mean = np.mean(test_scores, axis=1)
    test_std = np.std(test_scores, axis=1)

    plt.plot(train_sizes, train_mean,
             color='blue', marker='o',
             markersize=5, label='training accuracy')

    plt.fill_between(train_sizes,
                     train_mean + train_std,
                     train_mean - train_std,
                     alpha=0.15, color='blue')

    plt.plot(train_sizes, test_mean,
             color='green', linestyle='--',
             marker='s', markersize=5,
             label='validation accuracy')

    plt.fill_between(train_sizes,
                     test_mean + test_std,
                     test_mean - test_std,
                     alpha=0.15, color='green')

    plt.grid()
    plt.xlabel('Number of training samples')
    plt.ylabel('Accuracy')
    plt.legend(loc='lower right')
    plt.ylim([0.8, 1.0])
    plt.tight_layout()
    plt.show()

def validation(lr_tfidf, X_train, y_train):
    param_range = [0.001, 0.01, 0.1, 1.0, 10.0, 100.0]
    train_scores, test_scores = validation_curve(
        estimator=lr_tfidf,
        X=X_train,
        y=y_train,
        param_name='clf__C',
        param_range=param_range,
        cv=5)

    train_mean = np.mean(train_scores, axis=1)
    train_std = np.std(train_scores, axis=1)
    test_mean = np.mean(test_scores, axis=1)
    test_std = np.std(test_scores, axis=1)

    plt.plot(param_range, train_mean,
             color='blue', marker='o',
             markersize=5, label='training accuracy')

    plt.fill_between(param_range, train_mean + train_std,
                     train_mean - train_std, alpha=0.15,
                     color='blue')

    plt.plot(param_range, test_mean,
             color='green', linestyle='--',
             marker='s', markersize=5,
             label='validation accuracy')

    plt.fill_between(param_range,
                     test_mean + test_std,
                     test_mean - test_std,
                     alpha=0.15, color='green')

    plt.grid()
    plt.xscale('log')
    plt.legend(loc='lower right')
    plt.xlabel('Parameter C')
    plt.ylabel('Accuracy')
    plt.ylim([0.2, 1.0])
    plt.tight_layout()
    plt.show()

def confusion(lr_tfidf, X_train, y_train, X_test, y_test):
    lr_tfidf.fit(X_train, y_train)
    y_pred = lr_tfidf.predict(X_test)
    confmat = confusion_matrix(y_true=y_test, y_pred=y_pred)

    fig, ax = plt.subplots(figsize=(2.5, 2.5))
    ax.matshow(confmat, cmap=plt.cm.Blues, alpha=0.3)
    for i in range(confmat.shape[0]):
        for j in range(confmat.shape[1]):
            ax.text(x=j, y=i, s=confmat[i, j], va='center', ha='center')

    plt.xlabel('predicted label')
    plt.ylabel('true label')

    plt.tight_layout()
    plt.show()

if __name__ == '__main__':
    df = pd.read_csv('./movie_data.csv', encoding='utf-8')
    df.head(3)

    X = df.loc[:, 'review'].apply(preprocessor).values
    y = df.loc[:, 'sentiment'].values

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)

    tfidf = TfidfVectorizer(strip_accents=None,
                            lowercase=False,
                            preprocessor=None,
                            ngram_range=(1, 1),
                            tokenizer=tokenizer,
                            norm='l2')

    lr_tfidf = Pipeline([('vect', tfidf),
                         ('clf', LogisticRegression(random_state=0, penalty='l2', C=10.0))])

    scores = cross_val_score(estimator=lr_tfidf,
                             X=X_train,
                             y=y_train,
                             cv=5)
    print('CV accuracy scores: %s' % scores)
    print('CV accuracy: %.3f +/- %.3f' % (np.mean(scores), np.std(scores)))

    label = {0: 'negative', 1: 'positive'}
    example = []
    with open('probni.txt', 'r') as file:
        example.append(file.readline())

    lr_tfidf.fit(X_train, y_train)
    print('Prediction: %s\nProbability: %.2f%%' % \
          (label[lr_tfidf.predict(example)[0]], lr_tfidf.predict_proba(example).max() * 100))

    p1 = Process(name='daemon-learning_curve', target=learning, args=(lr_tfidf, X_train, y_train))
    p1.daemon = True
    p2 = Process(name='daemon-validation_curve', target=validation, args=(lr_tfidf, X_train, y_train))
    p2.daemon = True
    p3 = Process(name='daemon-confusion_matrix', target=confusion, args=(lr_tfidf, X_train, y_train, X_test, y_test))
    p3.daemon = True

    p1.start()
    p2.start()
    p3.start()

    p1.join()
    p2.join()
    p3.join()