from discord import Embed
import json
import urllib
from category import Category
from commands.command import Command

class News(Command):
    def __init__(self):
        aliases = ['news']
        shortdescription = "Get news from various sources. Uses https://newsapi.org/"
        longdescription = "Get the headlines from various news sources from https://newsapi.org/."
        usage = "/".join(aliases) + " <[source (default:google-news)]|info|available> [source]"
        category = Category.UNSURE

        # Get the key from config.json
        with open('config.json') as data_file:
            config = json.load(data_file)
        self.newskey = config['newskey']
        self.sources = json.load(
            urllib.request.urlopen('https://newsapi.org/v1/sources?language=en'))  # Get all available news sources
        super().__init__(aliases , shortdescription , longdescription , usage , category)

    def parse_time(self , unparsed):
        try:
            # Example unparsed string: 2017-11-03T13:46:07Z
            time = unparsed.split("T")[1][:-4]  # Get time and remove seconds
            date = unparsed.split("T")[0]  # Get complete date
            year = date.split("-")[0]
            month = date.split("-")[1]
            day = date.split("-")[2]
            return time + " on " + day + "." + month + "." + year  # Example return: "13:46 on 03.11.2017"
        except AttributeError:
            # Time was not available (for example on reddit-r-all)
            return "<not available>"

    async def execute(self , client , message , args , **kwargs):
        # at most 2 arguments
        if len(args) > 2:
            return False
        if len(args) != 0:
            if args[0] == "available":
                """ Lists all available news sources ids"""

                # Create embed Frame
                embed = Embed(title="Get more info about each source using 'news info [source]" , color=0xff8000)
                embed.set_author(name="Available news sources")
                categories = []  # All categories
                for source in self.sources['sources']:
                    if not source['category'] in categories:
                        categories.append(source['category'])  # Search for categories
                for category in categories:
                    category_text = ""  # For each category create a new field with this value
                    for source in self.sources[
                        'sources']:  # Add every news source with this value to the category value
                        if source['category'] == category:
                            category_text += source['id'] + "\n"
                    embed.add_field(name=category , value=category_text , inline=True)  # Add the category field
                await client.send_message(message.channel , embed=embed)  # Send the embed
                return True  # Command done

            if args[0] == "info":
                args.pop(0)  # Pop 'info' from the argument list
                if len(args) != 1:  # We need one more argument
                    return False

                for source in self.sources['sources']:
                    if source['id'] == args[0]:  # User wanted info about this source
                        # Create embed
                        embed = Embed(title="", description=source['description'] ,
                                      color=0xff8000)
                        embed.set_author(name=source['name'] , url=source['url'] ,
                                         icon_url="https://s2.googleusercontent.com/s2/favicons?domain=" + source[
                                             'url'])
                        embed.add_field(name="Category" , value=source['category'] , inline=True)
                        embed.add_field(name="Language" , value=source['language'] , inline=True)
                        embed.add_field(name="ID" , value=source['id'] , inline=True)

                        # Send the embed
                        await client.send_message(message.channel , embed=embed)
                        return True  # Command done

                # No news source with the name was found
                await client.send_message(message.channel , content="No news source with the name "
                                                                    + args[0] + " is available!")
                return True
            if len(args) != 1:
                # If the first argument is not info we don't need a second argument, thus throw syntax
                return False
            srcid = args[0]
        else:
            srcid = "google-news"

        for source in self.sources['sources']:
            if source['id'] == srcid:  # User wants news of this source
                api_url = "https://newsapi.org/v1/articles?source=" + source['id'] + "&apiKey=" + self.newskey
                news = json.load(urllib.request.urlopen(api_url))
                # Create embed with no title, title is basically the author, but author looks nicer and we can use
                # the favicon with that
                embed = Embed(title="" , color=0xff8000)
                embed.set_author(name=source['name'] , url=source['url'] ,
                                 icon_url="https://s2.googleusercontent.com/s2/favicons?domain=" + source['url'])
                for article in news['articles']:  # Add the articles as fields to the embed
                    embed = embed.add_field(name=article['title'] ,
                                            value=article['description'] + "\nPublished " + self.parse_time(
                                                article['publishedAt']) + "\n" + article['url'] ,
                                            inline=False)
                # Send the embed
                await client.send_message(message.channel , embed=embed)
                return True  # Done

        # No news source with the name was found
        await client.send_message(message.channel ,
                                  content="No news source with the name " + srcid + " is available!")
        return True  # Return true, we don't need to print syntax


"""The HTTP Client"""

from asyncio import AbstractEventLoop
import urllib.parse
from ssl import SSLContext
from typing import (
    AsyncIterable,
    Iterable,
    List,
    Optional,
    Tuple,
    Union
)

from .acgi import connect, RequestHandler
from .constants import DEFAULT_PROTOCOLS
from .middleware import HttpClientMiddlewareCallback
from .ssl_contexts import DEFAULT_CIPHERS, DEFAULT_OPTIONS
from .response import Response

class HttpClient:
    """An HTTP client"""

    def __init__(
            self,
            url: str,
            *,
            method: str = 'GET',
            headers: Optional[List[Tuple[bytes, bytes]]] = None,
            body: Optional[AsyncIterable[bytes]] = None,
            loop: Optional[AbstractEventLoop] = None,
            h11_bufsiz: int = 8096,
            cafile: Optional[str] = None,
            capath: Optional[str] = None,
            cadata: Optional[str] = None,
            ssl_context: Optional[SSLContext] = None,
            protocols: Iterable[str] = DEFAULT_PROTOCOLS,
            ciphers: Iterable[str] = DEFAULT_CIPHERS,
            options: Iterable[int] = DEFAULT_OPTIONS,
            connect_timeout: Optional[Union[int, float]] = None,
            middleware: Optional[List[HttpClientMiddlewareCallback]] = None
    ) -> None:
        """Make an HTTP client.

        The following example will make a GET request.

        ```python
        import asyncio
        from bareclient import HttpClient

        async def main(url: str) -> None:
            async with HttpClient(url, method='GET') as response:
                print(response)
                if response.status == 200 and response.body is not None:
                    async for part in response.body:
                        print(part)

        asyncio.run(main('https://docs.python.org/3/library/cgi.html'))
        ```

        Args:
            url (str): The url
            method (str, optional): The HTTP method. Defaults to 'GET'.
            headers (Optional[List[Tuple[bytes, bytes]]], optional): The headers. Defaults to
                None.
            body (Optional[AsyncIterable[bytes]], optional): The body content. Defaults to
                None.
            loop (Optional[AbstractEventLoop], optional): The optional asyncio
                event loop. Defaults to None.
            h11_bufsiz (int, optional): The HTTP/1 buffer size. Defaults to
                8096.
            cafile (Optional[str], optional): The path to a file of concatenated
                CA certificates in PEM format. Defaults to None.
            capath (Optional[str], optional): The path to a directory containing
                several CA certificates in PEM format. Defaults to None.
            cadata (Optional[str], optional): Either an ASCII string of one or
                more PEM-encoded certificates or a bytes-like object of
                DER-encoded certificates. Defaults to None.
            ssl_context (Optional[SSLContext], optional): An ssl context to be
                used instead of generating one from the certificates.
            protocols (Iterable[str], optional): The supported protocols. Defaults
                to DEFAULT_PROTOCOLS.
            ciphers (Iterable[str], optional): The supported ciphers. Defaults
                to DEFAULT_CIPHERS.
            options (Iterable[int], optional): The ssl.SSLContext.options. Defaults
                to DEFAULT_OPTIONS.
            connect_timeout (Optional[Union[int, float]], optional): The number
                of seconds to wait for the connection. Defaults to None.
            middleware (Optional[List[HttpClientMiddlewareCallback]], optional):
                Optional middleware. Defaults to None.
        """
        parsed_url = urllib.parse.urlparse(url)
        if parsed_url.hostname is None:
            raise ValueError('no hostname in url: ' + url)
        self.scheme = parsed_url.scheme
        self.netloc = parsed_url.netloc
        self.hostname = parsed_url.hostname
        self.path = parsed_url.path
        self.port = parsed_url.port

        self.method = method
        self.headers = headers
        self.body = body
        self.loop = loop
        self.h11_bufsiz = h11_bufsiz
        self.cafile = cafile
        self.capath = capath
        self.cadata = cadata
        self.ssl_context = ssl_context
        self.protocols = protocols
        self.ciphers = ciphers
        self.options = options
        self.connect_timeout = connect_timeout
        self.middleware = middleware or []

        self.handler: Optional[RequestHandler] = None

    async def __aenter__(self) -> Response:
        self.handler = RequestHandler(
            self.netloc,
            self.scheme,
            self.path,
            self.method,
            self.headers,
            self.body,
            self.middleware
        )
        response = await connect(
            self.scheme,
            self.hostname,
            self.port,
            self.handler,
            cafile=self.cafile,
            capath=self.capath,
            cadata=self.cadata,
            ssl_context=self.ssl_context,
            loop=self.loop,
            h11_bufsiz=self.h11_bufsiz,
            protocols=self.protocols,
            ciphers=self.ciphers,
            options=self.options,
            connect_timeout=self.connect_timeout
        )
        return response

    async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
        if self.handler is not None:
            await self.handler.close()


#!/usr/bin/env python3
"""
Replicate code from the previous task
"""
from typing import Tuple, List
import csv
import math

def index_range(page: int, page_size: int) -> Tuple[int, int]:
    """
    function named index_range that takes two integer arguments page and
    page_size
    """
    start = (page - 1) * page_size
    end = page * page_size
    return (start, end)

class Server:
    """Server class to paginate a database of popular baby names.
    """
    DATA_FILE = "Popular_Baby_Names.csv"

    def __init__(self):
        self.__dataset = None

    def dataset(self) -> List[List]:
        """Cached dataset
        """
        if self.__dataset is None:
            with open(self.DATA_FILE) as f:
                reader = csv.reader(f)
                dataset = [row for row in reader]
            self.__dataset = dataset[1:]

        return self.__dataset

    def get_page(self, page: int = 1, page_size: int = 10) -> List[List]:
        """Return the appropriate page of the dataset
        (i.e. the correct list of rows).
        """
        assert isinstance(page, int) and page > 0
        assert isinstance(page_size, int) and page_size > 0
        start, end = index_range(page, page_size)
        return self.dataset()[start:end]

    def get_hyper(self, page: int = 1, page_size: int = 10) -> List[List]:
        """Returns a dictionary with this key-value pairs:
        page_size: length of the returned dataset page
        page: current page number
        data: dataset page
        next_page: number of the next page, None if no next page
        prev_page: number of the previous page, None if no previous page
        total_pages: the total number of pages in the dataset as an integer
        """
        assert isinstance(page, int) and page > 0
        assert isinstance(page_size, int) and page_size > 0
        data = self.get_page(page, page_size)
        total_pages = math.ceil(len(self.dataset()) / page_size)
        next_page = page + 1 if page < total_pages else None
        prev_page = page - 1 if page > 1 else None
        hyper = {
            'page_size': len(data),
            'page': page,
            'data': data,
            'next_page': next_page,
            'prev_page': prev_page,
            'total_pages': total_pages
        }
        return hyper


# -*- coding: utf-8 -*-
from openerp import models, fields, api, exceptions

class planning(models.Model):
    _name = 'demand.planning'

    @api.one
    @api.depends('product_id')
    def _get_stock(self):
        if self.product_id:
            for op in self.product_id.orderpoint_ids:
                self.product_min_qty = op.product_min_qty
                self.product_min_qty_text =str(op.product_min_qty)
                self.product_max_qty = op.product_max_qty

            self.virtual_available = self.product_id.virtual_available
            self.virtual_available_text = str(self.product_id.virtual_available)
            self.qty_available = self.product_id.qty_available
            self.incoming_qty = self.product_id.incoming_qty
            self.outgoing_qty = self.product_id.outgoing_qty

    name = fields.Char('Planning Name', required=True)

    forecast_id = fields.Many2one('demand.forecast', string = 'Reference', required=True, domain=[('state','=','open')], readonly=True)
    forecast_lines = fields.One2many('demand.forecast.line', 'planning_id',string = 'Forecast Lines', readonly=True)
    planning_lines = fields.One2many('demand.planning.line', 'planning_id',string = 'Planning Lines', readonly=True, states={'draft': [('readonly',False)]})
    production_strategy = fields.Selection([('chasing','Chasing'),('level','Level')], "Plan Strategy" ,default='chasing', readonly=True, states={'draft': [('readonly',False)]})

    term_id= fields.Many2one('demand.term', string='Term', readonly=True)

    product_id = fields.Many2one('product.product',string="Product", readonly=True)
    product_uom = fields.Many2one('product.uom', string='Unit of Measure', readonly=True)

    virtual_available = fields.Float('Stock Accounting', readonly=True, compute=_get_stock)
    virtual_available_text = fields.Char(readonly =True, compute= _get_stock)
    qty_available = fields.Float('Stock On Hand', readonly=True, compute=_get_stock)
    incoming_qty = fields.Float('Incoming Quantity', readonly=True, compute=_get_stock)
    outgoing_qty = fields.Float('Outging Quantity', readonly=True, compute=_get_stock)

    warehouse_id = fields.Many2one('stock.warehouse', string="Warehouse", readonly=True, states={'draft': [('readonly',False)]})

    product_min_qty = fields.Float('Minimum Stock Rule', readonly=True, compute=_get_stock)
    product_min_qty_text = fields.Char(readonly =True, compute= _get_stock)
    product_max_qty = fields.Float('Maximum Stock Rule', readonly=True, compute=_get_stock)

    state = fields.Selection([
            ('draft', "Draft"),
            ('open', "Open"),
            ('close', "Close"),
            ], default='draft')
    @api.multi
    def action_draft(self):
        self.state = 'draft'

    @api.multi
    def action_open(self):
        self.state = 'open'

    @api.multi
    def action_close(self):
        self.state = 'close'
        self.forecast_id.state  = 'done'
        for line in self.forecast_lines:
            line.state = 'done'
        for line in self.planning_lines:
            line.state = 'close'

    @api.multi
    def action_view_orderpoint(self):
        orderpoint_lst = []
        orderpoint_obj = self.env['stock.warehouse.orderpoint']

        for op in orderpoint_obj:
            if op.product_id == self.product_id:
                orderpoint_lst.append(op.id)

        return {
            'view_mode': 'tree,form',
            'res_model': 'stock.warehouse.orderpoint',
            'res_id': orderpoint_lst,
            'view_id': False,
            'type': 'ir.actions.act_window',
            }

    @api.multi
    def _purchase_per_product(self, pe):
        # so_obj = self.env['sale.order']
        purchase_obj = self.env['purchase.order.line']

        # Kiem tra cac don hang ve san pham co ton tai
        pol_with_product = purchase_obj.search([('product_id','=',self.product_id.id), ('order_id.date_order','>=', pe.date_start), ('order_id.date_order','<=', pe.date_end)])
        if pol_with_product:
            sum_quantity = 0
            for pol in pol_with_product:
                sum_quantity += pol.product_qty
            return sum_quantity

    @api.multi
    def simulation_plans(self):
        ids = self.planning_lines.mapped('id')
        number_lines = len(ids)

        # Simulation plan
        first_plan_line = self.planning_lines.browse([ids[0]])
        first_plan_line.write({
            'qty_available': self.virtual_available,
            'incoming_qty': self._purchase_per_product(first_plan_line.period_id),
            })

        i = 1
        while i < number_lines:
            plan_line = self.planning_lines.browse([ids[i]])
            plan_line.write({
                'qty_available': self.product_min_qty,
                'incoming_qty': self._purchase_per_product(plan_line.period_id),
            })
            i += 1

        # Dien MPS theo chien luoc
        if self.production_strategy == 'chasing':
            for line in self.planning_lines:
                line.plan_qty = line.consult_qty
        elif self.production_strategy == 'level':
            sum_consult = 0
            for line in self.planning_lines:
                sum_consult += line.consult_qty
            average_consult = sum_consult/number_lines

            for line in self.planning_lines:
                line.plan_qty = average_consult

    @api.multi
    def execute_plans(self):
        for line in self.planning_lines:
            line.create_procurement()
        self.state = 'open'

class PlanningLine(models.Model):
    _name = 'demand.planning.line'

    @api.one
    @api.depends('qty_available', 'incoming_qty')
    def _calculate_consult_quantity(self):
        consult_quantity = self.forecast_line_id.forecast_qty - (self.qty_available + self.incoming_qty) + self.planning_id.product_min_qty
        if consult_quantity > 0:
            self.consult_qty = consult_quantity
        else:
            self.consult_qty = 0

    name = fields.Char('Planning Line Name', required=True)

    forecast_line_id = fields.Many2one('demand.forecast.line', string='Reference', required=True, readonly=True)
    planning_id = fields.Many2one('demand.planning', string='Source', required=True, readonly=True)
    procurement_id = fields.Many2one('procurement.order', string="Procurement", readonly=True)

    term_id= fields.Many2one('demand.term', string='Term', required=True, readonly=True)
    period_id = fields.Many2one('demand.period', string='Period', required=True, readonly=True)

    qty_available = fields.Float('Initial Stock', readonly=True)
    incoming_qty = fields.Float('Incoming Quantity', readonly=True)

    consult_qty = fields.Float('Consultant Quantity', readonly=True, compute=_calculate_consult_quantity)
    plan_qty = fields.Float('Procurement Quantity', required=True, default=0 ,readonly=True, states={'draft': [('readonly',False)]})

    state = fields.Selection([
            ('draft', "Draft"),
            ('open', "Open"),
            ('close', "Close"),
            ], default='draft')

    @api.multi
    def action_draft(self):
        self.state = 'draft'

    @api.multi
    def action_open(self):
        self.state = 'open'

    @api.multi
    def action_close(self):
        self.state = 'close'

    # @api.multi
    # def request_procurement(self):
    #     value_dict = {'product_id': self.planning_id.product_id.id,
    #                   'uom_id': self.planning_id.product_id.uom_id.id,
    #                   'date_planned': self.period_id.date_start,
    #                   'qty': self.plan_qty,
    #                   }
    #     res_id = self.env['make.procurement'].create(value_dict)
    #     self.state = 'open'

    #     return {'view_type': 'form',
    #             'view_mode': 'form',
    #             'res_model': 'make.procurement',
    #             'res_id': res_id.id,
    #             'view_id': False,
    #             'type': 'ir.actions.act_window',
    #             'target': 'new',
    #             }

    @api.multi
    def create_procurement(self):
        procurement_obj = self.env['procurement.order']
        if not self.procurement_id.exists():
            res_id = procurement_obj.create({
                    'name': 'Procurement ' +self.planning_id.product_id.name+ '('+self.period_id.name+')',
                    'date_planned': self.period_id.date_start,
                    'product_id': self.planning_id.product_id.id,
                    'product_uom': self.planning_id.product_id.uom_id.id,
                    'product_qty': self.plan_qty,
                    'warehouse_id': self.planning_id.warehouse_id.id,
                    'location_id': self.planning_id.warehouse_id.lot_stock_id.id,
                    'company_id': self.planning_id.warehouse_id.company_id.id,
                    'origin': self.planning_id.name,
                    })
            self.procurement_id = res_id.id
            self.state = 'open'

    @api.multi
    def show_procurement(self):
        return {
            'view_mode': 'form',
            'res_model': 'procurement.order',
            'res_id': self.procurement_id.id,
            'view_id': False,
            'type': 'ir.actions.act_window',
            }


'''
Decode a string recursively encoded as count followed by substring
An encoded string (s) is given, the task is to decode it.
The pattern in which the strings are encoded is as follows.
<count>[sub_str] ==> The substring 'sub_str'
                      appears count times.
Examples:
Input : str[] = "1[b]"
Output : b
Input : str[] = "2[ab]"
Output : abab
Input : str[] = "2[a2[b]]"
Output : abbabb
Input : str[] = "3[b2[ca]]"
Output : bcacabcacabcaca
'''

def DecodeString(str1):

    stk=[]
    output_list=[]
    for i in range(0,len(str1)):
        key=str1[i]
        if key==']':
            while stk[-1]!='[':
                output_list.insert(0,stk[-1])
                stk.pop()
            stk.pop()
            num=int(stk[-1])
            stk.pop()
            word=''.join(output_list)
            output_list=[]
            while num>0:
                output_list.append(word)
                num=num-1
        else:
            stk.append(key)
    return ''.join(output_list)

def main():

    str1='1[b]'
    print(DecodeString(str1))

    str1 = '2[ab]'
    print(DecodeString(str1))

    str1 = '2[a2[b]]'
    print(DecodeString(str1))

    str1 = '3[b2[ca]]'
    print(DecodeString(str1))

if __name__=='__main__':
    main()


# -*- coding: utf-8 -*-
"""
Created on Sat Oct  2 21:25:55 2021

@author: Rainbow
"""

import re
import copy
import codecs
import csv
import IPy
import os
import datetime

def makefiletext(filename):
    filedata = list()
    #file = codecs.open(filename,'r','utf-8')
    file = open(filename,'r')
    for line in file:
        filedata.append(line)
        #filedata.append(re.sub(r'\r\n','',line))
    file.close()

    #filetext = ''
    filetup = tuple(filedata)
    filetext = ''.join(filetup)
    return filetext

def makefiletextblock(filetext):

    filetextnospace = re.sub(r'^#\s*','#',filetext)
    filetextnon = re.sub(r'\n','|',filetextnospace)
    filetextblock = filetextnon.split(r'#')
    filetextblockline = list()
    for b in filetextblock:
        temp = b.split('|')
        if temp[0] == '':
            temp.pop(0)
        if temp[-1] == '':
            temp.pop(-1)
        filetextblockline.append(copy.deepcopy(temp))
    return filetextblockline

def getfilelocalandtype(filetext):
    prompt = r'<([\w|-]*)>'
    reprompt = re.compile(prompt)
    promptobj = reprompt.search(filetext)
    promptstr = promptobj.groups()[0]
    promptlist = promptstr.split('-')
    if len(promptlist) > 2:
        location = promptlist[0] + '-' + promptlist[1]
        devicetype = promptlist[2]
    else:
        location = promptlist[0]
        devicetype = promptlist[1]
    return location, devicetype

def getospfdict(filetextblockline):
    #print('-------------------In getospfdict funtion-------------------')
    #print(filetextblockline)
    ospfblock = list()
    reospf = r'^ospf'
    reo = re.compile(reospf)
    #reospfarea = r'^\s*(area)'
    reospfarea = r'^\s*(area\s*[\d|\.]*)'
    reoa = re.compile(reospfarea)
    reospfareanetwork = r'^\s*(network)'
    reoan = re.compile(reospfareanetwork)
    reospfareachange = r'^%*(area\s*[\d|\.]*)'
    reoac = re.compile(reospfareachange)
    for n in filetextblockline:
        if len(n) > 0:
            if reo.match(n[0]) != None:
                ospfblock.append(copy.deepcopy(n))
            else:
                pass
        else:
            pass
    #print(ospfblock)
    ospfblocksyb = list()
    for i in ospfblock:
        templist = list()
        for n in i:
            if reo.match(n) != None:
                templist.append(copy.deepcopy(n))
            elif reoa.search(n) != None:
                a = reoa.sub(r'#%\1%',n)
                templist.append(copy.deepcopy(a))
            elif reoan.search(n) != None:
                b = reoan.sub(r'||\1',n)
                templist.append(copy.deepcopy(b))
                #templist.append(copy.deepcopy(n))
        c = ''.join(templist)
        d = c.split('#')
        ospfblocksyb.append(copy.deepcopy(d))
    #print(ospfblocksyb)
    ospfdict = dict()
    tempdictlist = list()
    for o in ospfblocksyb:
        areanametemp = ['ospfarea',]
        areanumlisttemp = list()
        for i in o:
            #print('#----------ospf information,and add in dictlist---------------')
            if reo.search(i) != None:
                temp = (i.strip(' ')).split(' ')
                if len(temp) > 2:
                    tempdictlist.append(tuple(['ospfinstance',temp[0] + ' ' + temp[1]]))
                    tempdictlist.append(tuple(['ospfrouterid',temp[2] + ' ' + temp[3]]))
                else:
                    tempdictlist.append(tuple(['ospfinstance',temp[0] + ' ' + temp[1]]))
                    tempdictlist.append(tuple(['ospfrouterid','']))
            else:
                pass
            #print('#----------ospf area information, make dict and add in dictlist---------')
            if reoac.search(i) != None:
                arealinelist = (i.strip(' ').split('%'))
                areainfo = arealinelist[1]

                areainfolist = (areainfo.strip(' ')).split(' ')
                areanumber = areainfolist[1]
                areanumlisttemp.append(areanumber)

                areanetinfo = arealinelist[2]
                areanetlist = (areanetinfo.strip(' ')).split('||')
                areanetlist.pop(0)

                areanumtemp = list()
                areanetlisttemp = list()
                areanumtemp.append(areanumber)
                for n in areanetlist:
                    b = (n.strip(' ')).split(' ')
                    netm = b[2].split('.')
                    netmtemp = list()
                    for m in netm:
                        netmtemp.append(str(255 - int(m)))
                    c = str(IPy.IP(b[1]).make_net('.'.join(netmtemp)))
                    areanetlisttemp.append(c)
                areanumtemp.append(areanetlisttemp)
                tempdictlist.append(tuple(areanumtemp))
        areanametemp.append(areanumlisttemp)
        tempdictlist.append(tuple(areanametemp))
    #print(tempdictlist)
    ospfdict = dict(tempdictlist)
    #print(ospfdict)
    return ospfdict

if __name__ == '__main__':
    configpath = r'....pleas type youself file dirctory....'
    anaylispath =r'....pleas type youself file dirctory....'
    curr_time = datetime.datetime.now()
    time_str = datetime.datetime.strftime(curr_time,'%Y-%m-%d_%H-%M-%S')
    filename = r'ospf-configuration' + '_' + time_str + '.csv'
    filefullname = anaylispath + '\\' + filename

    os.chdir(configpath)
    refiledotname = r'.txt$'
    refen = re.compile(refiledotname)
    dirfile = os.listdir()
    txtfilelist = list()
    for f in dirfile:
        if refen.search(f) != None:
            txtfilelist.append(f)

    fileslist = list()
    for f in txtfilelist:
        fileslist.append(configpath + '\\' + f)

    allospfconfig = list()
    for f in fileslist:
        print(f)
        templist = list()
        tempdict = dict()
        ftxt = makefiletext(f)
        ftxtb = makefiletextblock(ftxt)
        dlocal,dtype = getfilelocalandtype(ftxt)
        ospfd = getospfdict(ftxtb)

        templist.append(tuple(['devicelocation',dlocal]))
        templist.append(tuple(['devicetype',dtype]))
        tempdict = dict(templist)
        tempdict.update(ospfd)
        allospfconfig.append(copy.deepcopy(tempdict))
    #for os in allospfconfig:
    #    print(os)

    csvline = list()
    csvhead = tuple(['devicelocation','devicetype','ospfinstance','ospfrouterid','ospfarea','subnetwork'])
    for o in allospfconfig:
        for a in o['ospfarea']:
            asubnet = o[a]
            for n in asubnet:
                tempospf = list()
                #print(n)
                tempospf.append(o['devicelocation'])
                tempospf.append(o['devicetype'])
                tempospf.append(o['ospfinstance'])
                tempospf.append(o['ospfrouterid'])
                tempospf.append(a)
                tempospf.append(n)
                csvline.append(tuple(tempospf))
    #print(csvline)

    filew = codecs.open(filefullname,'w','utf-8')
    wf = csv.writer(filew)
    wf.writerow(csvhead)
    for l in csvline:
        wf.writerow(l)
    filew.close()

    print("+-----------All of files in <{}> was scan, {} files. Ospf routes infomation is {}, write to file <{}>.-----------+".format(configpath,len(fileslist),len(csvline),filefullname))


#!/user/bin/env python3

#Dictionaries 1
dictionary = {
	"name" : "Chris",
	"city" : "Seattle",
	"cake" : "Chocolate"
}

print(dictionary)

del dictionary['cake']

print(dictionary)

dictionary['fruit'] = "Mango"

print(dictionary)

print(dictionary.keys())

print(dictionary.values())

print("cake" in dictionary.keys())

print("Mango" in dictionary.values())

#Dictionaries 2

def count_t(word):
	return word.lower().count('t')

dictionary_2 = {}

for (i, key) in enumerate(dictionary):
	dictionary_2[key] = count_t(dictionary[key])

print(dictionary_2)

#Sets

s2 = set()
s3 = set()
s4 = set()

for i in range(1, 20):
	if i % 2 == 0:
		s2.add(i)

for i in range(1, 20):
	if i % 3 == 0:
		s3.add(i)

for i in range(1, 20):
	if i % 4 == 0:
		s4.add(i)

print("s2: ", s2)
print("s3: ", s3)
print("s4: ", s4)

print("Is s3 a subset of s2: ", s3.issubset(s2))
print("Is s4  a subset of s2: ", s4.issubset(s2))

#Set 2
Python = set()
for letter in "Python":
	print(letter)
	Python.add(letter)
#Python.add('i')
print(Python)


import game_utils
import interp
import merc

# noinspection PyUnusedLocal
def cmd_shadowsight(ch, argument):
    if ch.is_npc():
        return

    if ch.is_demon() or ch.special.is_set(merc.SPC_CHAMPION):
        if not ch.dempower(merc.DEM_SHADOWSIGHT):
            ch.send("You haven't been granted the gift of shadowsight.\n")
            return
    elif not ch.is_werewolf() or ch.powers[merc.WPOWER_HAWK] < 2:
        if not ch.is_vampire():
            ch.huh()
            return

        if not ch.vampaff.is_set(merc.VAM_OBTENEBRATION):
            ch.send("You are not trained in the Obtenebration discipline.\n")
            return

    if ch.is_affected(merc.AFF_SHADOWSIGHT):
        ch.send("You can no longer see between planes.\n")
        ch.affected_by.rem_bit(merc.AFF_SHADOWSIGHT)
        return

    if ch.is_vampire():
        if ch.blood < 10:
            ch.send("You have insufficient blood.\n")
            return

        ch.blood -= game_utils.number_range(5, 10)

    ch.send("You can now see between planes.\n")
    ch.affected_by.set_bit(merc.AFF_SHADOWSIGHT)

interp.register_command(
    interp.CmdType(
        name="shadowsight",
        cmd_fun=cmd_shadowsight,
        position=merc.POS_SITTING, level=3,
        log=merc.LOG_NORMAL, show=True,
        default_arg=""
    )
)


# -*- coding:utf-8 -*-
import os
from app.utils.clean_word import clean_word
from app.utils.similar_word.find_related_words import load_file
from pyltp import Segmentor, SentenceSplitter, Postagger, NamedEntityRecognizer, Parser

import sys
basepath = os.path.abspath('.')
sys.path.append(basepath)
path = os.getcwd()

LTP_DATA_DIR = path + '\\app\\model\\' # ltp模型目录的路径
cws_model_path = os.path.join(LTP_DATA_DIR, 'cws.model')
pos_model_path = os.path.join(LTP_DATA_DIR, 'pos.model')  # 词性标注模型路径，模型名称为`pos.model`
ner_model_path = os.path.join(LTP_DATA_DIR, 'ner.model')  # 命名实体识别模型路径，模型名称为`pos.model`
par_model_path = os.path.join(LTP_DATA_DIR, 'parser.model')  # 依存句法分析模型路径，模型名称为`parser.model`

def cut_sentence(string):
    '''
    分句函数
    @intput string: A long text with lots of sentences.
    @output: list[sentence1,sentence2]
    '''
    sents = SentenceSplitter.split(string)
    sentences = [s for s in sents if len(s) !=0]

    return sentences

def cut_word(sentence):
    '''
    分词函数
    @input:[sentence1,sentence2,...]
    @output: [word_1,word_2,....]
    '''
    words = []
    for sents in sentence:
        words += clean_word(sents).split(' ')
    return words

def word_pos(sents):
    '''
    词性标注函数
    @input: [sentence1, sentence2,...]
    @切词在函数内进行
    @output: [postag1, postag2, ....]
    '''
    postagger = Postagger()
    postagger.load(pos_model_path)

    words = cut_word(sents)
    postag = postagger.postag(words)

    postagger.release()
    return list(postag)

def ner(words, pos):
    '''
    命名实体识别函数
    @ input: cut_word:List  postag: List
    @ output: Name Entity Recognizer: List
    @ explanation: Nh:人名   Ni:机构名 Ns:地名 S:这个词单独构成一个NE
    '''
    recognizer = NamedEntityRecognizer()
    recognizer.load(ner_model_path)

    netags = recognizer.recognize(words, pos)
    recognizer.release()
    return list(netags)

def dependency_parsing(words, pos):
    '''
    依存句法分析函数
    @ input: cut_word-->List  pos--> List
    @ output: [(index, relationship)] -->List
      arc.head 表示依存弧的父节点词的索引，arc.relation 表示依存弧的关系。
      pyltp的算法只有一个root节点
    '''
    parser = Parser()
    parser.load(par_model_path)

    arcs = parser.parse(words, pos)
    parser.release()
    return [(arc.head, arc.relation) for arc in arcs]

def extract_news(cut_sents, say_word):
    '''
    @ input: cut_sents-->List,切分的句子； say_word-->List，相近的单词
    @ output : Result --> List 人物及观点
    '''
    result = []
    for index, sentence in enumerate(cut_sents):
        person = ''
        say = ''
        comment = ''
        word = cut_word([sentence])
        postags = word_pos([sentence])
        ner_tag = ner(word, postags)
        parser = dependency_parsing(word, postags)

        if ('S-Nh' in ner_tag) or ('S-Ni' in ner_tag) or ('S-Ns' in ner_tag):
            # 存在命名实体
            # 判断 SBV and say word 是否存在
            for i, p in enumerate(parser):
                if (p[1] == 'SBV') and word[p[0] - 1] in say_word:  # verb 位置 = p[0] -1
                    # 满足主谓， 且包含‘说’
                    person = word[i]
                    say = word[p[0] - 1]
                    if word[p[0]] == '，' or word[p[0]] == ',':
                        comment = ''.join(word[p[0] + 1:])
                    else:
                        comment = ''.join(word[p[0]:])
                else:
                    continue
        else:
            # 不存在命名实体
            continue
        result.append(('对应文中第{}句'.format(index+1), person, say, comment))
    return result

def present_data(string):
    '''
    封装函数
    @ input : string ---> text
    @ output: extractor result including: person, say_word, comment
    '''
    # path = './similar_word/'
    path = basepath + '\\app\\utils\\similar_word\\'
    say_word = load_file(path + 'similar_word_to_say.txt')
    sents = cut_sentence(string)
    res = []
    person_comment = extract_news(sents, say_word)
    for r in person_comment:
        dic1 = {}
        dic1['name'] = r[1]
        dic1['action'] = r[2]
        dic1['words'] = r[3]
        # res[r[1]] = (r[2],r[3],r[0])
        # res[r[1]] =  r[3]
        res.append(dic1)

    return res

# if __name__ == '__main__':
#     test_string = '''
#     特区行政会议当天复会。林郑月娥在出席会议前对传媒表示，过去一星期，大规模恶意破坏行动在香港各区蔓延，包括堵塞铁路、瘫痪机场、围堵过海隧道、攻击各区警署等，使市民出行和上下班受到影响。有人使用汽油弹、烟雾弹等升级武器攻击警务人员，导致
#     警员受伤。她指出，一些人以自由或正义的名义，但其实不断做出破坏行为，目无法纪，损害香港法治。小芳表示理解。
#     '''
#     short_test = '小明表示"这块土地是他承包的。"土地上的苹果也是他的。小芳表示她很认同。小张和小明一起去上学。'
#     another_test = '小明表示"这块土地是他承包的。"'
#
#
#
#
#     print(present_data(test_string))


# -*- coding: utf-8 -*-
"""
Created on Fri Jun 22 14:44:49 2018

@author: Jens Reichwein

Shows a GUI with input parameters. The parameters can be plotted, saved and the blade can be seen in 3D
The aerodynamic values of the blades are stored in .txt files for Re- numbers of 50.000. They can be generated using XFoil.
So far, only 4-digit NACA airfoils can be used.
A correction for number of blades could not be succesfully implemented, as the values for the tip showed impossible values.

Input: design wind speed, design rotations, design rotor radius, .txt files of aerodynamic values
Output: bladed design with chord and twist distribution.
"""

import numpy as np
import matplotlib.pyplot as plt

try:
    import IPython
    shell = IPython.get_ipython()
    shell.enable_matplotlib(gui='qt')
except:
    print('failed')

#########
###############          entries          #####################################
    def BEM(self):
        self.rotor_diameter         = 0.2                                       # rotor diameter
        self.hub_diameter           = 0.056                                     # hub diameter
        self.rotations              = 3000                                      # rotations
        self.v_des                  = 15                                        # wind speed
        self.Blades                 = 3                                         # blades
        self.sections               = 15                                        # sections
        self.efficiency             = 80                                        # efficiency
        self.airfoil                = 'NACA_2418'                               # airfoil
###############################################################################
###############          functions           ##################################
        self.aerodynamics()
        self.fix_blades()
###############################################################################
    def aerodynamics(self):
        self.Profile            = self.airfoil
        self.Re_init            = 100000
        try:
            self.Re
        except AttributeError:
            link = 'Airfoils/polars/' + str(self.Profile) + '/Montgomerie/' + str(self.Profile) + '_T1_Re'+str('{:.3f}'.format(((self.Re_init)/10e5))) + '_M0.00_N9.0_360_M.dat'
        else:
            self.base = 5000
            self.Re = int(self.base * round(float(self.Re)/self.base))

            link = 'Airfoils/polars/' + str(self.Profile) + '/Montgomerie/' + str(self.Profile) + '_T1_Re'+str('{:.3f}'.format(((self.Re)/10e5))) + '_M0.00_N9.0_360_M.dat'

        with open(link, 'r') as fp:
            for i in range (15):
                next(fp)
            data = fp.read()
            alpha = []
            c_L = []
            c_D = []
            for line in data.splitlines():
                temp = line.split()
                if temp:
                    alpha.append(eval(temp[0]))
                    c_L.append(eval(temp[1]))
                    c_D.append(eval(temp[2]))
                else:
                    break

        L2D = [ x/c_D[i] for i,x in enumerate(c_L) ]
        alpha_pos = L2D.index(max(L2D[10:]))
        self.alpha = alpha[alpha_pos]
        self.cl = c_L[alpha_pos]
        self.cd = c_D[alpha_pos]

    def calculation(self):
        '''
        Input:  rotor diameter, hub diameter, rotations, design wind velocity, Airfoil, amount of sections, efficiency, if desired: amount of blades
        Requirements: txt. data of the aerodynamic values of the used airfoils in the same folder
        Output: BEM code calculated parameters: local radii, chord-/ twist-distribution, thrust, torque, power (-coefficients)
        '''
        self.aerodynamics()

        self.frequency          = self.rotations /60
        self.Omega              = 2*np.pi*self.frequency

        self.nu                 = 15.11*10**-6
        self.rho                = 1.225

        self.Radius             = self.rotor_diameter/2
        self.hub_radius         = self.hub_diameter/2
        self.d_r                = (self.Radius- self.hub_radius)/(self.sections-1)

        self.TSR                = self.Omega * self.Radius / self.v_des
        self.v_tip              = self.Omega*self.Radius

        self.A                  = np.pi * (self.Radius**2 -  self.hub_radius**2)
        self.P_w                = 0.5* self.rho * self.v_des**3 * self.A
        self.P_t                = self.P_w * 16/27
        self.Method             = 'mixed'#'Glauert' #'straight Line' 'Wilson-Walker' 'mixed'

        #################################################################################
        print('{:^8}| {:^8}| {:^8}| {:^8}| {:^8}| {:^8}| {:^8}| {:^8}| {:^8}| {:^8}| {:^8}| {:^8}| {:^8}'.format("a'",'a',"Radius","ax. ind.","chord", 'c/R', 'Twist', 'Re', 'solidity','c_P', 'F', 'f_tip', 'f_tip'))

        self.a_ax_list          = []
        self.a_rot_list         = []

        self.chord_list         = []
        self.Re_list            = []
        self.twist_list         = []
        self.v_app_list         = []

        self.F_list             = []

        self.c_T_list           = []
        self.c_P_list           = []

        self.T_list             = []
        self.M_list             = []
        self.P_list             = []

        self.radius_list        = []

        self.a_ax_init       = 0.0
        self.a_rot_init      = 0.001
        self.delta_a         = 1.0
        for i in range(self.sections-1):
            self.radius          = self.hub_radius + (i*self.d_r+(i+1)*self.d_r)/2
            self.radius_list.append(self.radius)

            while abs(self.delta_a)> 10e-8:#self.a_ax_init < self.a_ax:#abs(a_ax - a_ax_init)>0:#a_ax > a_ax_init:#

                self.v_rot          = self.radius*2*np.pi*self.frequency
                self.v_app          = np.sqrt((self.v_des*(1-self.a_ax))**2+(self.v_rot*(1+self.a_rot))**2)

                self.TSR_local      = self.TSR * self.radius / self.Radius

                self.phi_rad        = np.arctan(((1-self.a_ax)*self.v_des)/((1+self.a_rot)*(self.Omega*self.radius)))
                self.phi_deg        = np.rad2deg(self.phi_rad)

                self.twist          = self.phi_deg-self.alpha
###############        Prandtl Correction             ##########################
                self.f_tip          = 2/np.pi*(np.arccos(np.exp(-(self.B/2 *((self.Radius-self.radius)/(self.radius * np.sin(self.phi_rad)))))))
                self.f_hub          = 2/np.pi*(np.arccos(np.exp(-(self.B/2 *((self.radius-self.hub_radius)/(self.radius * np.sin(self.phi_rad)))))))
                self.F              = self.f_tip*self.f_hub

                self.chord          = 8*np.pi*self.radius*np.sin(self.phi_rad)/(3*self.B*self.cl*self.TSR_local)

                self.d_L            = 0.5*self.rho*self.chord*self.v_app**2*self.cl*self.d_r#*radius
                self.d_D            = 0.5*self.rho*self.chord*self.v_app**2*self.cd*self.d_r#*radius

                self.cn             = self.cl*np.cos(self.phi_rad) + self.cd*np.sin(self.phi_rad)
                self.cr             = self.cl*np.sin(self.phi_rad) - self.cd*np.cos(self.phi_rad)

                self.a_rot          = 1/((4*self.F*(np.sin(self.phi_rad)*np.cos(self.phi_rad)))/(self.cr*self.solidity)-1)

                self.d_T_MOM        = 4*np.pi*self.radius*self.rho*self.v_des**2*(1-self.a_ax)*self.a_ax*self.d_r*self.F
                self.d_M_MOM        = 4*np.pi*self.radius*self.rho*self.v_des*(self.Omega*self.radius**2*(1-self.a_ax))*self.a_rot*self.d_r*self.F

                self.d_T_BE         = self.B*self.cn *0.5*self.rho*self.chord*(self.v_app**2)*self.d_r
                self.d_M_BE         = self.B*self.cr *0.5*self.rho*self.chord*(self.v_app**2)*self.radius*self.d_r

                self.solidity       = self.B*self.chord/(2*np.pi*self.radius)

                if self.Method == 'Glauert':
                    if self.a_ax <= 0.4:
                        self.a_ax = 1/self.F*(0.143 + np.sqrt(0.0203-0.6427*(0.899-self.c_T)))
                        self.c_T = self.F*self.solidity*(1-self.a_ax)**2*(self.cl*self.cn/(np.sin(self.phi_rad)*np.sin(self.phi_rad)))

                self.count       += 1
                self.delta_a     = self.a_ax_init - self.a_ax

#                self.B_EP = self.a_ax/(1+self.a_rot)*4*np.sin(self.phi_rad)
#                self.chord2 = self.B_EP *2*np.pi*self.v_des/(self.B*self.cl*self.Omega)

                self.Re = self.v_app*self.chord/self.nu

                self.epsilon = self.cd/self.cl
                self.eta = (1-self.epsilon*(1/np.tan(self.phi_rad)*(1/np.tan(self.phi_rad))/((1/np.tan(self.phi_rad)+self.epsilon))))

                self.c_P = 4*self.a_ax*(1-self.a_ax)**2
                self.d_c_P = 2*(1-self.a_ax)*self.a_rot *self.TSR**2*(self.radius/self.Radius)**4

                self.d_a = abs(self.a_ax_init-self.a_ax)

                if self.a_ax_init+self.a_ax >0:
                    self.a_ax_init = (self.a_ax_init+self.a_ax)/2

###############        Correction Methods            ##########################
                self.c_T = (1-self.a_ax)**2*self.solidity*self.cn/(np.sin(self.phi_rad)*np.sin(self.phi_rad))

                self.T = 0.5*self.rho*self.c_T*np.pi*self.radius**2*self.v_des**2
                self.P = self.Omega*self.d_M_BE*self.efficiency

            self.a_ax_list.append(self.a_ax),       self.a_rot_list.append(self.a_rot)
            self.chord_list.append(self.chord)
            self.c_P_list.append(self.c_P)
            self.c_Thrust_list.append(self.c_T)
            self.F_list.append(self.F)
            self.M_list.append(self.d_M_BE)
            self.P_list.append(self.P)

            self.Re_list.append(self.Re)#,          self.Re2_list.append(self.rey2)
            #self.F_list.append(self.F)
            #self.Thrust_list.append(self.d_T_BE)
            self.Thrust_list.append(self.T)
            #self.T2_list.append(self.T2)
            self.twist_list.append(self.twist)
            self.v_app_list.append(self.v_app), self.T_list.append(self.d_T_BE)
            #self.T_list.append(self.d_T_MOM)
            print('{:>8,.3f}| {:>8.3f}| {:>8.3f}| {:>8.3f}| {:>8.3f}| {:>8.3f}| {:>8.3f}| {:>8,.0f}| {:>8.3f}| {:>8.3f}| {:>8.3f}| {:>8.3f}| {:>8.3f}| {:>8.3f}'.format(self.a_rot, self.a_ax_init, self.radius, self.a_ax_init, self.chord, self.chord/self.Radius, self.twist, self.Re, self.solidity, self.c_P, self.F, self.f_tip, self.f_hub, self.phi_rad))
        self.M_tot = sum(self.M_list)
        self.P_tot = sum(self.P_list)*self.efficiency

###############################################################################
###############          print           ######################################
        print(50 * '--')
        print('{:<15s}: {:>10.3f} m | {:<15s}: {:>10.0f}   | {:<15s}: {:>10.4f} m'.format      ('Rot Diameter', self.rotor_diameter,'Sections', self.sections -1, 'delta r', self.d_r))
        print('{:<15s}: {:>10s}   | {:<15s}: {:>10.3f} m/s'.format          ('Profile', self.profile, 'des. wind speed', self.v_des))
        print('{:<15s}: {:>10.0f}   | {:<15s}: {:>10.3f} rpm'.format          ('Blades', self.B, 'Rotations', self.rotations))
        if self.v_tip > 80:
            print('{:<15s}: {:>10.3f} m/s -> above 80 m/s'.format   ('Tip velocity', self.v_tip, ))
        else:
            print('{:<15s}: {:>10.3f} m/s -> below 80 m/s'.format   ('Tip velocity', self.v_tip))
        print('{:<15s}: {:>10.3f}   '.format       ('TSR', self.TSR, ))
        print('{:<15s}: {:>10.3f} W | {:<15s}: {:>10.3f} W | {:<15s}: {:>10.3f} W | {:<15s}: {:>10.3f} %'.format('Power wind', self.P_w, 'Power Betz', self.P_t, 'Power WT', self.P_tot, 'Efficiency η', 100*self.P_tot/self.P_w))
        print('{:<15s}: {:>10.3f}   | {:<15s}: {:>10.3f}   | {:<15s}: {:>10.3f} ° | {:<15s}: {:>10.3f} '.format('lift coeff.', self.cl, 'drag coeff.', self.cd, 'AoA', self.alpha, 'L2D', self.cl/self.cd))
        print('{:<15s}: {:>10.3f} Nm'.format('Torque WT', self.M_tot))
        print(50*'--')
###############################################################################
###############          plot           #######################################
    def plotting(self):
        if self.plot.get() == 1:

            plt.figure('plots', figsize=(10,5))
            plt.title(self.profile)
            ax1 = plt.subplot(221)
            plt.xlabel('Radius [m]')
            plt.ylabel('Twist [°]')
            plt.xlim(0,self.Radius*1.1)
            plt.ylim(0.0, 36.0)
            plt.minorticks_on()
            plt.grid(True,which='major')
            plt.grid(True,which='minor', linestyle='--')
            ax1.plot(self.radius_list,self.twist_list, color = 'k', marker = '.')

            ax2 = plt.subplot(222)
            plt.xlabel('Radius [m]')
            plt.ylabel('Chord [m]')
            plt.xlim(0,self.Radius*1.1)
            plt.ylim(0.0, 0.12)
            plt.minorticks_on()
            plt.grid(True,which='major')
            plt.grid(True,which='minor', linestyle='--')
            ax2.plot(self.radius_list,self.chord_list, color = 'k', marker = '.')

            ax3 = plt.subplot(223)
            plt.xlabel('Radius [m]')
            plt.ylabel('Re [-]')
            plt.xlim(0,self.Radius*1.1)
            plt.ylim(0,100000)
            plt.minorticks_on()
            plt.grid(True,which='major')
            plt.grid(True,which='minor', linestyle='--')
            ax3.plot(self.radius_list,self.Re_list, color = 'k', marker = '.')

            ax4 = plt.subplot(224)
            plt.xlabel('Radius [m]')
            plt.ylabel('apparent wind velocity [m/s]')
            plt.xlim(0,self.Radius*1.1)
            plt.ylim(0,80)
            plt.minorticks_on()
            plt.grid(True,which='major')
            plt.grid(True,which='minor', linestyle='--')
            ax4.plot(self.radius_list,self.v_app_list, color = 'k', marker = '.')

            plt.show()

###############################################################################
#self.F = 1
#chord       = 16*np.pi/(self.B) * radius/self.cl * (np.sin(1/3 * np.arctan(self.Radius/radius/self.TSR)))**2
#chord       = 8 * F*radius*np.pi*np.sin(phi_rad)/(self.B*self.cl)*((1-self.TSR_local*np.tan(phi_rad))/(np.tan(phi_rad+self.TSR_local)))
#self.chord       = 8*np.pi*self.radius/(self.B*self.cl)*(1-np.cos(self.phi_rad))

#                if self.Method == 'straight Line':
#                    self.c_T1 = 1.816
#                    self.c_T = self.c_T1 -4 *(np.sqrt(self.c_T1)-1)*(1-self.a_ax)
#
#                if self.Method == 'Wilson-Walker':
#                    self.a_ac = 0.2
#                    self.K = 4*self.F*np.sin(self.phi_rad)*np.sin(self.phi_rad)/(self.solidity*self.cn)
#                    if self.a_ax <= self.a_ac:
#                        self.c_T = 4*self.F*self.a_ax*(1-self.a_ax)
#                    elif self.a_ax >0.2:
#                        self.a_ax = 1/2*(2+self.K*(1-2*self.a_ac))-np.sqrt((self.K*(1-2*self.a_ac)**2+4*(self.K*self.a_ax**2-1)))
#                        self.c_T = 4*self.F*(self.a_ac**2+self.a_ax*(1-2*self.a_ac))
#                if self.Method == 'this one':
#                    self.a_c = 0.2
#                    if self.a_ax <= self.a_c:
#                        self.K           = 4*self.F*np.sin(self.phi_rad)*np.sin(self.phi_rad)/(self.solidity*self.cn)
#                        self.a_ax       = 1/(self.K+1)
#                    else:
#                    #    self.a_ax    = 1/((4*self.F*(np.sin(self.phi_rad)*np.sin(self.phi_rad)))/(self.cn*self.solidity)+1)
#                        self.a_ax    = 1/2*(2+self.K*(1-2*self.a_c)-np.sqrt((self.K*(1-2*self.a_c)+2)**2+4*(self.K*self.a_c**2-1)))

            #                self.a_c = 0.2
#
#                if self.a_ax <= self.a_c:
#                    self.K          = 4*self.F*np.sin(self.phi_rad)*np.sin(self.phi_rad)/(self.solidity*self.cn)
#                    self.a_ax       = 1/(self.K+1)
#                else:
#                #    self.a_ax    = 1/((4*self.F*(np.sin(self.phi_rad)*np.sin(self.phi_rad)))/(self.cn*self.solidity)+1)
#                    self.a_ax    = 1/2*(2+self.K*(1-2*self.a_c)-np.sqrt((self.K*(1-2*self.a_c)+2)**2+4*(self.K*self.a_c**2-1)))


# https://github.com/dalek7/umbrella/blob/6901d2774349f46aec566f200d8844c76c40ccc9/MFC/OFMathTest/lib/ofQuaternion.cpp#L68-L142
# https://github.com/jinyunp/rotation_with_quaternion
def makeRotation(v1, v2):
    from scipy.spatial.transform import Rotation as R
    import numpy as np
    import math

    v1 = v1 / np.linalg.norm(v1)
    v2 = v2 / np.linalg.norm(v2)

    dot_product = 1.0 + np.dot(v1, v2)

    s = math.sqrt(0.5 * dot_product)
    tmp = np.cross(v1, v2) / (2.0 * s)

    # q = np.quaternion()
    # q.x = tmp[0]
    # q.y = tmp[1]
    # q.z = tmp[2]
    # q.w = s

    r = R.from_quat([tmp[0], tmp[1], tmp[2], s])
    # r = R.from_quat([q.x, q.y, q.z, q.w])

    return r.as_matrix()

# v1 as an arbitrary axis which is rotated to unit vector of z-axis
v1 = [-0.03, -0.3, 0.5]
v2 = [0, 0, 1]

R = makeRotation(v1, v2)
print(R)
print()
import numpy as np

v1_norm = v1 / np.linalg.norm(v1)
v1_transformed = R.dot(np.transpose(v1_norm))
print(v1_transformed)
'''
[[ 0.99857782 -0.01422176  0.05138162]
 [-0.01422176  0.85778243  0.51381615]
 [-0.05138162 -0.51381615  0.85636026]]
'''


class Solution:
    def maximumSwap(self, num: int) -> int:
        a=[]
        while(num!=0):
            a.append(num%10)
            num//=10
        a.reverse()
        t=[[a[i],i] for i in range(len(a))]
        def key(val):
            return [1/(val[0]+1),val[1]]
        t.sort(key=key)
        # print(t,a)
        for i in range(len(a)):
            if(a[i]!=t[i][0]):
                k=i+1
                while(k<(len(a)) and t[k][0]==t[i][0]):
                    k+=1
                k-=1
                # print(k,i,a)
                a[i],a[t[k][1]]=a[t[k][1]],a[i]
                break
        ans=0
        for i in range(len(a)):
            ans=(ans*10)+a[i]
        return ans


import operator
from abc import abstractmethod
import random

import constants

class BaseOracle:

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

    @abstractmethod
    def get_super_arm(self, q_function, context_vectors, bandit_arms, epsilon):
        pass

    @staticmethod
    def removed_covered_v2(arm_ucb_dict, chosen_id, bandit_arms, remaining_memory):
        """
        second version which is based on the remaining memory and already chosen arms

        :param arm_ucb_dict: dictionary of arms and upper confidence bounds
        :param chosen_id: chosen arm in this round
        :param bandit_arms: Bandit arm list
        :param remaining_memory: max_memory - used_memory
        :return: reduced arm list
        """
        reduced_arm_ucb_dict = {}
        for arm_id in arm_ucb_dict:
            if not (bandit_arms[arm_id] <= bandit_arms[chosen_id] or bandit_arms[arm_id].memory > remaining_memory):
                reduced_arm_ucb_dict[arm_id] = arm_ucb_dict[arm_id]
        return reduced_arm_ucb_dict

    @staticmethod
    def removed_covered_tables(arm_ucb_dict, chosen_id, bandit_arms, table_count):
        """

        :param arm_ucb_dict: dictionary of arms and upper confidence bounds
        :param chosen_id: chosen arm in this round
        :param bandit_arms: Bandit arm list
        :param table_count: count of indexes already chosen for each table
        :return: reduced arm list
        """
        reduced_arm_ucb_dict = {}
        for arm_id in arm_ucb_dict:
            if not (bandit_arms[arm_id].table_name == bandit_arms[chosen_id].table_name and table_count[
                    bandit_arms[arm_id].table_name] >= constants.MAX_INDEXES_PER_TABLE):
                reduced_arm_ucb_dict[arm_id] = arm_ucb_dict[arm_id]
        return reduced_arm_ucb_dict

    @staticmethod
    def removed_covered_clusters(arm_ucb_dict, chosen_id, bandit_arms):
        """

        :param arm_ucb_dict: dictionary of arms and upper confidence bounds
        :param chosen_id: chosen arm in this round
        :param bandit_arms: Bandit arm list
        :return: reduced arm list
        """
        reduced_arm_ucb_dict = {}
        for arm_id in arm_ucb_dict:
            if not (bandit_arms[arm_id].table_name == bandit_arms[chosen_id].table_name and bandit_arms[
                chosen_id].cluster is not None and bandit_arms[arm_id].cluster is not None and bandit_arms[
                        arm_id].cluster == bandit_arms[chosen_id].cluster):
                reduced_arm_ucb_dict[arm_id] = arm_ucb_dict[arm_id]
        return reduced_arm_ucb_dict

    @staticmethod
    def removed_covered_queries_v2(arm_ucb_dict, chosen_id, bandit_arms):
        """
        When covering index is selected for a query we gonna remove all other arms from that query
        :param arm_ucb_dict: dictionary of arms and upper confidence bounds
        :param chosen_id: chosen arm in this round
        :param bandit_arms: Bandit arm list
        :return: reduced arm list
        """
        reduced_arm_ucb_dict = {}
        for arm_id in arm_ucb_dict:
            query_ids = bandit_arms[chosen_id].query_ids
            for query_id in query_ids:
                if (bandit_arms[arm_id].table_name == bandit_arms[chosen_id].table_name and bandit_arms[
                        chosen_id].is_include == 1 and query_id in bandit_arms[arm_id].query_ids):
                    bandit_arms[arm_id].query_ids.remove(query_id)
            if bandit_arms[arm_id].query_ids != set():
                reduced_arm_ucb_dict[arm_id] = arm_ucb_dict[arm_id]
        return reduced_arm_ucb_dict

class OracleDDQN(BaseOracle):

    def get_super_arm(self, q_function, context_vectors, bandit_arms, epsilon):
        used_memory = 0
        chosen_arms = []
        arm_ucb_dict = {}
        table_count = {}

        for i in range(len(bandit_arms)):
            arm_ucb_dict[i] = q_function[i]

        while len(arm_ucb_dict) > 0:
            if random.random() < epsilon:
                max_ucb_arm_id = random.sample(list(arm_ucb_dict), 1)[0]
            else:
                max_ucb_arm_id = max(arm_ucb_dict.items(), key=operator.itemgetter(1))[0]

            if bandit_arms[max_ucb_arm_id].memory < self.max_memory - used_memory:
                chosen_arms.append(max_ucb_arm_id)
                used_memory += bandit_arms[max_ucb_arm_id].memory
                if bandit_arms[max_ucb_arm_id].table_name in table_count:
                    table_count[bandit_arms[max_ucb_arm_id].table_name] += 1
                else:
                    table_count[bandit_arms[max_ucb_arm_id].table_name] = 1
                arm_ucb_dict = self.removed_covered_tables(arm_ucb_dict, max_ucb_arm_id, bandit_arms, table_count)
                arm_ucb_dict = self.removed_covered_clusters(arm_ucb_dict, max_ucb_arm_id, bandit_arms)
                arm_ucb_dict = self.removed_covered_queries_v2(arm_ucb_dict, max_ucb_arm_id, bandit_arms)
                arm_ucb_dict = self.removed_covered_v2(arm_ucb_dict, max_ucb_arm_id, bandit_arms,
                                                       self.max_memory - used_memory)
            else:
                arm_ucb_dict.pop(max_ucb_arm_id)

        return chosen_arms


import pathlib

#Paths and File Processing
p = pathlib.Path('./')
for f in p.iterdir():
    print(f.absolute())

with open("test.txt", "r") as infile, open("copy.txt", "w") as outfile:
    for line in infile:
        outfile.write(line)
    print("Copied test.txt")

with open("test.png", "rb") as infile, open("copy.png", "wb") as outfile:
    for byte in infile:
        outfile.write(byte)
    print("Copied test.png")

#used set to prevent repeted entries
languages = set()
with open("students.txt") as data:
    #throw away the first line
    data.readline()
    for raw in data:
        #throw away student name
        line = raw.split(':')[1].split(',')
        for word in line:
            #ignore nickname, and clean up whitespace and /n
            if word.islower(): languages.add(word.strip())

print(languages)


from odoo import fields, models

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    milestone = fields.Integer(string='Milestone')

class ProjectProject(models.Model):
    _inherit = 'project.project'

    project_id = fields.Char(string="project id")

class ProjectTask(models.Model):
    _inherit = 'project.task'

    task_id = fields.Char(string="task id")
    milestone_id = fields.Char(string="milestone id")
    product_id = fields.Char(string="product id")

class CreateProject(models.Model):
    _inherit = 'sale.order'

    project = fields.Boolean(copy=False)

    def button_create_project(self):

        project = self.env['project.project'].create({
            'name': self.name,
            'project_id': self.id,
            'partner_id': self.partner_id.id
        })
        milestone_list = []
        for rec in self.order_line:
            milestone_list.append(rec.milestone)
        non_dup = [*set(milestone_list)]
        for non_duplicate in non_dup:
            project_id = self.env['project.project'].search(
                [('id', '=', project.id)])
            if non_duplicate:
                new = rec.env['project.task'].create({
                    'name': 'Milestone ' + str(non_duplicate),
                    'task_id': self.id,
                    'milestone_id': non_duplicate,
                    'project_id': project_id.id
                })
                for rec in self.order_line:
                    if rec.milestone == non_duplicate:
                        new.write({
                            'child_ids': [(0, 0, {
                                'name': new.name + ' - ' + rec.product_id.name,
                                'product_id': rec.product_id.id
                            })]
                        })
        self.project = True

    def button_update_project(self):
        for rec in self.order_line:
            project_exist = self.env['project.project'].search(
                [('project_id', '=', self.id)])
            record_milestone = rec.milestone
            if record_milestone:
                task_exist = self.env['project.task'].search(
                    [('milestone_id', '=', record_milestone),
                     ('project_id', '=', project_exist.id)])
                if task_exist:
                    child_exist = self.env['project.task'].search(
                        [('parent_id', '=', task_exist.name),
                         ('product_id', '=', rec.product_id.id)
                         ])
                    if not child_exist:
                        task_exist.write({
                            'child_ids': [(0, 0, {
                                'name': task_exist.name + ' - ' + rec.product_id.name,
                                'product_id': rec.product_id.id
                            })]
                        })
                else:
                    new_task = rec.env['project.task'].create({
                        'name': 'Milestone ' + str(record_milestone),
                        'task_id': self.id,
                        'milestone_id': record_milestone,
                        'project_id': project_exist.id
                    })
                    new_task.write({
                        'child_ids': [(0, 0, {
                            'name': new_task.name + ' - ' + rec.product_id.name,
                            'product_id': rec.product_id.id
                        })]
                    })

    def get_project(self):
        self.ensure_one()
        return {
            'type': 'ir.actions.act_window',
            'name': 'project',
            'view_mode': 'tree,form',
            'res_model': 'project.project',
            'domain': [
                ('project_id', '=', self.id)],
            'context': "{'create': False}"
        }


"""
17.18 Shortest Subsequence: You are given two arrays, one shorter (with all distinct elements) and one
longer. Find the shortest subarray in the longer array that contains all the elements in the shorter
array. The items can appear in any order

example:
Input:  [1, 5, 9]
        [7, 5, 9, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 8, 9, 7]
"""
from collections import defaultdict

class Window:
    def __init__(self, minlen):
        self.minlen = minlen
        self.left = 0
        self.right = 0

def shortest_subsequence(short, long):
    # as they are distinct I won't save a dict, just a set to keep track
    target = set(short)
    visited = defaultdict(int)
    left = 0
    right = 0
    window = Window(len(long))
    while right < len(long):
        while right < len(long) and target > visited.keys():
            if long[right] in target:
                visited[long[right]] += 1
            right += 1
        while left < right and target == visited.keys():
            if right - left < window.minlen:
                window.minlen = right - left
                window.left = left
                window.right = right
            visited[long[left]] -= 1
            if visited[long[left]] <= 0:
                del visited[long[left]]

            left += 1

    return [window.left, window.right - 1]

if __name__ == "__main__":
    short = [1, 5, 9]
    longer = [7, 5, 9, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 8, 9, 7]
    print(shortest_subsequence(short, longer))


from setuptools import setup, find_packages
import os

here = os.path.abspath(os.path.dirname(__file__))

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

setup(
    name='regru_cloudapi',
    description='Reg.ru CloudAPI Python library',
    version='1.2.13',
    url='https://github.com/plvskiy/regru_cloudapi',
    author='Matthew Polovskiy',
    author_email='github@plvskiy.ru',
    packages=find_packages(),
    python_requires='>=3.6',
    long_description=read('README.md'),
    long_description_content_type='text/markdown',
    license='MIT',
    classifiers=['Programming Language :: Python :: 3',
                 'License :: OSI Approved :: MIT License'
                 ],
    install_requires=[
        'setuptools==65.4.1',
        'requests==2.28.1'
    ]
)


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

from odoo import models, fields, api

class BaseScheduleNotification(models.Model):
    _name = 'base.schedule.notification'

    name = fields.Char('Name', required=True)
    action_id = fields.Many2one('ir.cron','Scheduled Action')
    partner_ids = fields.Many2many('res.partner', string='Recipients')
    type = fields.Selection([('Email', 'Email'), ('SMS','SMS'), ('Push Notification','Push Notification')], string="Type", default='Email', required=True)
    active = fields.Boolean('Active', default=True)
    days = fields.Integer('Period (Days)')
    note = fields.Text('Note')

    @api.multi
    def toggle_active(self):
        super(BaseScheduleNotification, self).toggle_active()
        for record in self:
            if record.action_id:
                record.action_id.toggle_active()

class IrCron(models.Model):
    _inherit = 'ir.cron'

    view_on_notification = fields.Boolean('View On Notifications')


from LinkedList import LinkedList

print("\nMusic Playlist")
print("--------------")
print('Powered by LinkedList\u2122 technology.')
print("--------------")

LinkedList = LinkedList()
commandList = ["append", "prepend",
               "find", "reverse", "delete", "print", "exit"]
stopProgram = False

while not stopProgram:
    print("--------------")
    print("Enter a command: append, prepend, find, reverse, delete, print, exit")
    command = input().lower()
    while command not in commandList:
        print("Enter a valid command")
        command = input().lower()

    if command == "append":
        print("enter song name")
        name = input().lower()
        LinkedList.append(name)

    if command == "prepend":
        print("enter song name")
        name = input().lower()
        LinkedList.prepend(name)

    if command == "find":
        print("enter song name to find")
        name = input().lower()
        print(f'Song Found: {LinkedList.find(name)}')

    if command == "reverse":
        LinkedList.reverse()

    if command == "delete":
        print("enter song name to delete")
        name = input().lower()

        if name == LinkedList.tail:
            LinkedList.delete_from_tail()
        else:
            LinkedList.delete(name)

    if command == "print":
        print("--------------")
        LinkedList.printList()

    if command == "exit":
        print("exiting...")
        stopProgram = True


from typing import Callable, List, Union

import numpy as np
import numpy.typing as npt

# def is_sorted(xx: np.array) -> bool:
#     x_prev = xx[0]
#     for x in xx:
#         if x < x_prev:
#             return False
#         x = x_prev
#     return True
## 80 times slower on sorted input...
def is_sorted(xx: npt.NDArray) -> bool:
    return np.all(xx[:-1] <= xx[1:])

# type defs
TranslationInt = Union[npt.NDArray, int, List[int]]
TranslationFloat = Union[npt.NDArray, float, List[float]]
FrameType = Union[npt.NDArray, int, List[int], List[int]]

def cast_to_numpy_arrays(
    x: Union[TranslationInt, TranslationFloat],
    frame: FrameType,
):
    if isinstance(frame, int):
        frame = np.array([frame], dtype=np.uint32)
    if isinstance(frame, list):
        frame = np.array(frame, dtype=np.uint32)
    if isinstance(x, (float, int)):
        x = np.array([x])  # type will be changed later: this is a scalar anyway
    if isinstance(x, list):
        x = np.array(
            x
        )  # OK, this is potentially more expensive, simply use arrays to avoid that.
    return (x, frame)

def translate_values_frame_sorted(
    x_frame_sorted: npt.NDArray,
    frame_sorted: npt.NDArray,
    bruker_translator_foo: Callable,
    x_dtype,
    result_dtype,
) -> npt.NDArray:
    assert x_dtype in (
        np.double,
        np.uint32,
    ), f"Wrong x_dtype: Bruker code only uses np.double and np.uint32, not {x_dtype}."
    assert result_dtype in (
        np.double,
        np.uint32,
    ), f"Wrong result_dtype: Bruker code only uses np.double and np.uint32, not {x_dtype}."
    if x_frame_sorted.dtype != x_dtype:
        x_frame_sorted = x_frame_sorted.astype(x_dtype)
    if frame_sorted.dtype != np.uint32:
        frame_sorted = frame_sorted.astype(np.uint32)
    result = np.empty(x_frame_sorted.shape, dtype=result_dtype)
    if len(result) == 0:
        return result
    i_prev = 0
    frame_id_prev = frame_sorted[0]
    for i, frame_id in enumerate(frame_sorted):
        if frame_id != frame_id_prev:
            result[i_prev:i] = bruker_translator_foo(
                frame_id_prev,
                x_frame_sorted[i_prev:i],
            )
            i_prev = i
        frame_id_prev = frame_id
    result[i_prev : len(result)] = bruker_translator_foo(
        frame_id_prev,
        x_frame_sorted[i_prev : len(result)],
    )
    return result

def translate_values_frames_not_guaranteed_sorted(
    x: npt.NDArray,
    frame: npt.NDArray,
    **kwargs,
) -> npt.NDArray:
    frames_are_sorted = is_sorted(frame)
    if frames_are_sorted:
        frame_sorted = frame
        x_frame_sorted = x
    else:
        order = np.argsort(frame)
        frame_sorted = frame[order]
        x_frame_sorted = x[order]
    result_sorted = translate_values_frame_sorted(
        x_frame_sorted=x_frame_sorted,
        frame_sorted=frame_sorted,
        **kwargs,
    )
    if frames_are_sorted:
        result = result_sorted
    else:
        result = result_sorted[np.argsort(order)]
    return result


import os
import logging

from airflow import DAG
from airflow.utils.dates import days_ago
from airflow.operators.bash import BashOperator
from airflow.operators.python import PythonOperator
import pyarrow.csv as pv
import pyarrow.parquet as pq
from google.cloud import storage
from airflow.providers.google.cloud.operators.bigquery import BigQueryCreateExternalTableOperator

#set up logging
logger = logging.getLogger(__name__)

#variables
#load_dotenv()

dataset_file = "yellow_tripdata_2021-01.csv.gz"
dataset_url = f"https://github.com/DataTalksClub/nyc-tlc-data/releases/download/yellow/{dataset_file}"
path_to_local_home = os.environ.get("AIRFLOW_HOME", "/opt/airflow/")
parquet_file = dataset_file.replace('.csv.gz', '.parquet')

logger.info(f'Dataset file is {dataset_file}, url is {dataset_url}, local_home is {path_to_local_home}, parquet file is {parquet_file}')

#GCP environment variables
BUCKET=os.environ.get("GCP_GCS_BUCKET")
PROJECT_ID=os.environ.get("GCP_PROJECT_ID")
PROJECT_NAME=os.environ.get("GOOGLE_CLOUD_PROJECT")
BIGQUERY_DATASET=os.environ.get("BIGQUERY_DATASET", 'trips_data_all')

logger.info(f'{BUCKET} is the bucket, {PROJECT_NAME} is the project name, {PROJECT_ID} is the project id, {BIGQUERY_DATASET} is the bigquery dataset.')

#set default args for the dag
default_args = {
    "owner": "admin",
    "start_date": days_ago(1),
    "depends_on_past": False,
    "retries": 1,
}

def format_to_parquet(src_file):
    if not (src_file.endswith('.csv') or src_file.endswith('.csv.gz')):
        logger.error("Can only accept source files in CSV format, for the moment")
        return
    table = pv.read_csv(src_file)
    if(src_file.endswith('.csv')):
        pq.write_table(table, src_file.replace('.csv', '.parquet'))
    else:
        pq.write_table(table, src_file.replace('.csv.gz', '.parquet'))

def upload_to_gcs(bucket, object_name, local_file):
    """
    Ref: https://cloud.google.com/storage/docs/uploading-objects#storage-upload-object-python
    :param bucket: GCS bucket name
    :param object_name: target path & file-name
    :param local_file: source path & file-name
    :return:
    """
    # WORKAROUND to prevent timeout for files > 6 MB on 800 kbps upload speed.
    # (Ref: https://github.com/googleapis/python-storage/issues/74)
    storage.blob._MAX_MULTIPART_SIZE = 5 * 1024 * 1024  # 5 MB
    storage.blob._DEFAULT_CHUNKSIZE = 5 * 1024 * 1024  # 5 MB
    # End of Workaround

    client = storage.Client()
    #bucket = client.bucket(bucket)
    bucket = client.get_bucket(bucket)

    blob = bucket.blob(object_name)
    logger.info(f'Blob is {blob}')
    blob.upload_from_filename(local_file)

with DAG(dag_id="data_ingestion_gcs_dag",
         schedule_interval="@daily",
         default_args=default_args,
         catchup=False,
         max_active_runs=1,
         tags=['dtc-de']) as dag:

    download_dataset_task = BashOperator(
        task_id="download_dataset_task",
        bash_command=f"curl -sSL {dataset_url} > {path_to_local_home}/{dataset_file}"
    )

    format_to_parquet_task = PythonOperator(
        task_id="format_to_parquet_task",
        python_callable=format_to_parquet,
        op_kwargs={
            "src_file": f"{path_to_local_home}/{dataset_file}"
        }
    )

    local_to_gcs_task = PythonOperator(
        task_id="local_to_gcs_task",
        python_callable=upload_to_gcs,
        op_kwargs={
            "bucket": BUCKET,
            "object_name": f"raw/{parquet_file}",
            "local_file": f"{path_to_local_home}/{parquet_file}"
        }
    )

    bigquery_external_table_task = BigQueryCreateExternalTableOperator(
        task_id="bigquery_external_table_task",
        table_resource={
            "tableReference": {
                "projectId": PROJECT_ID,
                "datasetId": BIGQUERY_DATASET,
                "tableId": "external_table"
            },
            "externalDataConfiguration": {
                "sourceFormat": "PARQUET",
            "sourceUris": [f"gs://{BUCKET}/raw/{parquet_file}"]
            }
        }
    )

download_dataset_task >> format_to_parquet_task >> local_to_gcs_task >> bigquery_external_table_task