from __future__ import absolute_import, unicode_literals

from six.moves import xrange

from django.db import models
from django.core.exceptions import ValidationError
try:
    from django.contrib.contenttypes.forms import BaseGenericInlineFormSet
except ImportError:
    from django.contrib.contenttypes.generic import BaseGenericInlineFormSet
from django.contrib.contenttypes.models import ContentType
from django.forms.models import BaseInlineFormSet

try:
    # Django 1.6
    from django.utils.encoding import force_text as force_unicode
except ImportError:
    # Django <= 1.5
    from django.utils.encoding import force_unicode

class NestedInlineFormSetMixin(object):

    def save(self, commit=True):
        """
        Saves model instances for every form, adding and changing instances
        as necessary, and returns the list of instances.
        """
        self.changed_objects = []
        self.deleted_objects = []
        self.new_objects = []

        # Copied lines are from BaseModelFormSet.save()
        if not commit:
            self.saved_forms = []
            def save_m2m():
                for form in self.saved_forms:
                    form.save_m2m()
            self.save_m2m = save_m2m
        # End copied lines from BaseModelFormSet.save()

        # The above if clause is the entirety of BaseModelFormSet.save(),
        # along with the following return:
        # return self.save_existing_objects(commit) + self.save_new_objects(commit)

        # Iterate through self.forms and add properties `_list_position`
        # and `_is_initial` so that the forms can be put back in the
        # proper order at the end of the save method.
        #
        # We need to re-sort the forms because we can get ForeignKey
        # constraint errors if we save nested formsets in their default order.
        initial_form_count = self.initial_form_count()
        forms = []
        for i, form in enumerate(self.forms):
            form._list_position = i
            form._is_initial = bool(i < initial_form_count)
            forms.append(form)

        # Perform the sort (and allow extended logic in child classes)
        forms = self.process_forms_pre_save(forms)

        form_instances = []
        saved_instances = []

        for form in forms:
            instance = self.get_saved_instance_for_form(form, commit, form_instances)
            if instance is not None:
                # Store saved instances so we can reference it for
                # sub-instanced nested beneath not-yet-saved instances.
                saved_instances += [instance]
            else:
                instance = form.instance
            if not self._should_delete_form(form):
                form_instances.append(instance)

        # Re-sort back to original order
        saved_instances.sort(key=lambda i: i._list_position)
        return saved_instances

    def process_forms_pre_save(self, forms):
        """
        Sort by the sortable_field_name of the formset, if it has been set.

        Allows customizable sorting and modification of self.forms before
        they're iterated through in save().

        Returns list of forms.
        """
        sortable_field_name = getattr(self, 'sortable_field_name', None)
        if sortable_field_name is not None:
            default_data = {}
            default_data[sortable_field_name] = 0
            def sort_form(f):
                data = getattr(f, 'cleaned_data', default_data)
                return data.get(sortable_field_name, 0)
            forms.sort(key=sort_form)
        return forms

    def get_saved_instance_for_form(self, form, commit, form_instances=None):
        pk_name = None
        if form.instance and form.instance._meta.pk:
            pk_name = form.instance._meta.pk.name
        pk_val = None
        if not form.errors and hasattr(form, 'cleaned_data'):
            pk_val = form.cleaned_data.get(pk_name)
        # Inherited models will show up as instances of the parent in
        # cleaned_data
        if isinstance(pk_val, models.Model):
            pk_val = pk_val.pk
        if pk_val is not None:
            try:
                setattr(form.instance, pk_name, pk_val)
            except ValueError:
                pk_attname = form.instance._meta.pk.get_attname()
                setattr(form.instance, pk_attname, pk_val)

        if form._is_initial:
            instances = self.save_existing_objects([form], commit)
        else:
            instances = self.save_new_objects([form], commit)
        if len(instances):
            instance = instances[0]
            instance._list_position = form._list_position
            return instance
        else:
            return None

    def get_queryset(self):
        """
        TODO: document this extended method
        """
        if not self.data:
            return super(NestedInlineFormSetMixin, self).get_queryset()

        if not hasattr(self, '__queryset'):
            pk_keys = ["%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
                       for i in xrange(0, self.initial_form_count())]
            pk_vals = [self.data.get(pk_key) for pk_key in pk_keys if self.data.get(pk_key)]

            mgr = self.model._default_manager
            if hasattr(mgr, 'get_queryset'):
                # Django 1.6
                qs = mgr.get_queryset()
            else:
                # Django <= 1.5
                qs = mgr.get_query_set()

            qs = qs.filter(pk__in=pk_vals)

            # If the queryset isn't already ordered we need to add an
            # artificial ordering here to make sure that all formsets
            # constructed from this queryset have the same form order.
            if not qs.ordered:
                qs = qs.order_by(self.model._meta.pk.name)

            self.__queryset = qs
        return self.__queryset

    def _existing_object(self, pk):
        """
        TODO: document this extended method
        """
        if not hasattr(self, '_object_dict'):
            self._object_dict = dict([(o.pk, o) for o in self.get_queryset()])
        obj = self._object_dict.get(pk)
        if not obj:
            try:
                obj = self.model.objects.get(pk=pk)
            except self.model.DoesNotExist:
                pass
        return obj

    def _construct_form(self, i, **kwargs):
        """
        Because of the fact that existing objects can be added to inlines
        from other inlines, we sometimes get the wrong instance back.
        For instance, if an item from inline B was dragged to the top of
        inline A, and inline A already had items in it, form.instance would
        be set to the instance that was originally the first item in inline A.
        This patch fixes this problem.
        """
        form = super(NestedInlineFormSetMixin, self)._construct_form(i, **kwargs)
        pk_value = form.data.get(form.add_prefix(self._pk_field.name))
        if pk_value == '':
            pk_value = None
        if pk_value and force_unicode(form.instance.pk) != force_unicode(pk_value):
            model_cls = form.instance.__class__
            try:
                form.instance = model_cls.objects.get(pk=pk_value)
            except model_cls.DoesNotExist:
                pass
            else:
                setattr(form.instance, self.fk.get_attname(), self.instance.pk)
        return form

    def save_existing_objects(self, initial_forms=None, commit=True):
        """
        Identical to parent class, except ``self.initial_forms`` is replaced
        with ``initial_forms``, passed as parameter.
        """
        if not initial_forms:
            return []

        saved_instances = []

        if hasattr(self, 'deleted_forms'):
            # Django 1.6
            forms_to_delete = self.deleted_forms
        else:
            # Django <= 1.5
            forms_to_delete = [f for f in initial_forms
                               if self.can_delete and self._should_delete_form(f)]

        for form in initial_forms:
            pk_name = self._pk_field.name

            if not hasattr(form, '_raw_value'):
                # Django 1.9+
                raw_pk_value = form.fields[pk_name].widget.value_from_datadict(
                    form.data, form.files, form.add_prefix(pk_name))
            else:
                raw_pk_value = form._raw_value(pk_name)

            # clean() for different types of PK fields can sometimes return
            # the model instance, and sometimes the PK. Handle either.
            if self._should_delete_form(form):
                pk_value = raw_pk_value
            else:
                try:
                    pk_value = form.fields[pk_name].clean(raw_pk_value)
                except ValidationError:
                    # The current form's instance was initially nested under
                    # a form that was deleted, which causes the pk clean to
                    # fail (because the instance has been deleted). To get
                    # around this we clear the pk and save it as if it were new.
                    form.data[form.add_prefix(pk_name)] = ''
                    saved_instances.extend(self.save_new_objects([form], commit))
                    continue
                pk_value = getattr(pk_value, 'pk', pk_value)

            obj = None
            if obj is None and form.instance and pk_value:
                model_cls = form.instance.__class__
                try:
                    obj = model_cls.objects.get(pk=pk_value)
                except model_cls.DoesNotExist:
                    if pk_value and force_unicode(form.instance.pk) == force_unicode(pk_value):
                        obj = form.instance
            if obj is None:
                obj = self._existing_object(pk_value)

            if form in forms_to_delete:
                self.deleted_objects.append(obj)
                obj.delete()
                continue

            # fk_val: The value one should find in the form's foreign key field
            new_ct_val = ct_val = ContentType.objects.get_for_model(self.instance.__class__)
            new_fk_val = fk_val = self.instance.pk
            if form.instance.pk:
                original_instance = self.model.objects.get(pk=form.instance.pk)
                fk_field = getattr(self, 'fk', getattr(self, 'ct_fk_field', None))
                if fk_field:
                    new_fk_val = getattr(original_instance, fk_field.get_attname())
                ct_field = getattr(self, 'ct_field', None)
                if ct_field:
                    new_ct_val = getattr(original_instance, ct_field.get_attname())

            if form.has_changed() or fk_val != new_fk_val or ct_val != new_ct_val:
               self.changed_objects.append((obj, form.changed_data))
               saved_instances.append(self.save_existing(form, obj, commit=commit))
               if not commit:
                   self.saved_forms.append(form)
        return saved_instances

    def save_new_objects(self, extra_forms=None, commit=True):
        """
        Identical to parent class, except ``self.extra_forms`` is replaced
        with ``extra_forms``, passed as parameter, and self.new_objects is
        replaced with ``new_objects``.
        """
        new_objects = []

        if extra_forms is None:
            return new_objects

        for form in extra_forms:
            if not form.has_changed():
                continue
            # If someone has marked an add form for deletion, don't save the
            # object.
            if self.can_delete and self._should_delete_form(form):
                continue
            new_objects.append(self.save_new(form, commit=commit))
            if not commit:
                self.saved_forms.append(form)

        self.new_objects.extend(new_objects)
        return new_objects

class NestedInlineFormSet(NestedInlineFormSetMixin, BaseInlineFormSet):
    """
    The nested InlineFormSet for the common case (ForeignKey inlines)
    """
    pass

class GenericNestedInlineFormSet(NestedInlineFormSetMixin, BaseGenericInlineFormSet):
    """
    The nested InlineFormSet for inlines of generic content-type relations
    """

    @classmethod
    def get_default_prefix(cls):
        opts = cls.model._meta
        return '-'.join((opts.app_label, opts.object_name.lower(),
                        cls.ct_field.name, cls.ct_fk_field.name))


import datetime

# Function to check if a number is prime
def is_prime(n):
    if n <= 1:
        return False  # Numbers less than 2 are not prime numbers
    if n <= 3:
        return True  # 2 and 3 are prime numbers
    if n % 2 == 0 or n % 3 == 0:
        return False  # Numbers divisible by 2 or 3 are not prime
    i = 5
    while i * i <= n:  # We only need to check divisibility up to the square root of n
        if n % i == 0 or n % (i + 2) == 0:
            return False  # If n is divisible by any number, it's not prime
        i += 6
    return True  # If n is not divisible by any number, it's prime

# Function to calculate the next year when the person's age will be a prime number
def next_prime_age_year(birth_year):
    current_year = datetime.date.today().year  # Get the current year
    age = current_year - birth_year  # Calculate the person's current age
    while True:  # Keep looping until we find a prime age
        age += 1  # Increment the age
        if is_prime(age):  # Check if the incremented age is prime
            return birth_year + age  # If it is, return the year when the person will be of that age

if __name__ == "__main__":
    while True:  # Start an infinite loop
        birth_year = input("Please enter your birth year or 'q' to quit: ")  # Ask for input
        if birth_year.lower() == 'q':  # If the user entered 'q' or 'Q', break the loop
            break
        birth_year = int(birth_year)  # Convert the input to an integer
        print("The next year when your age will be a prime number is: ", next_prime_age_year(birth_year))  # Calculate and print the result


SYMBOL_BEATS = {"ROCK": "SCISSOR", "SCISSOR": "PAPER", "PAPER": "ROCK"}
TRANSLATE = {"ROCK": ["A", "X"], "PAPER": ["B", "Y"], "SCISSOR": ["C", "Z"]}
MIN_SCORE = {"ROCK": 1, "PAPER": 2, "SCISSOR": 3}

def load_input(fname):
    with open(fname) as fh:
        return fh.readlines()

def translate(symbol):
    for key, vals in TRANSLATE.items():
        if symbol in vals:
            return key
    raise NotImplementedError(f"Did not find {symbol}")

def parse_input(lines):
    result = []
    for line in lines:
        first, second = line.strip().split(" ")
        result.append([translate(first), translate(second)])
    return result

def key_at_value(value):
    for key, val in SYMBOL_BEATS.items():
        if val == value:
            return key

def parse_input_second(lines):
    result = []
    for line in lines:
        first, second = line.strip().split(" ")
        first = translate(first)
        if second == "X":
            second = SYMBOL_BEATS[first]
        elif second == "Y":
            second = first
        elif second == "Z":
            second = key_at_value(first)

        result.append([first, second])
    return result

def score(player, opponent):
    if player == opponent:
        return 3

    if SYMBOL_BEATS[player] == opponent:
        return 6
    return 0

def sum_score(rounds):
    return sum([score(player=r[1], opponent=r[0]) + MIN_SCORE[r[1]] for r in rounds])

content = load_input("input.txt")
rounds = parse_input(content)

print(sum_score(rounds))

rounds = parse_input_second(content)
print(sum_score(rounds))


import matplotlib.pyplot as plt
import math
import numpy  as np
import random

class Dice():
    def __init__(self,numSides=6):
        try:

            # if numOf sides of dice is less than 4 or decimal exception is raised
            if(numSides<4 or (type(numSides) != int) ):
                raise Exception;
            else:

                # if specified number of sides of the dice, by default equal probabilities
                # is given to each face of the dice, which can be modified later
                self.numSides = numSides;
                self.probs = tuple(np.full(self.numSides, float(1/self.numSides)));

                # ls stores the partition of the interval (0,1) according to the probability of each face
                self.ls = [];
        except Exception:
            print("Cannot construct the dice");

    def setProb(self,prob=None):

        # if probilities are specified (by default every face has equal probabilty)
        # we check if sum of all probabilities is 1 and whether probability of each face is given
        if(prob != None):
            sumi = sum(prob);
            try:

                # here round function is used to get precision till 4 in oreder to prevent the inaccuracy resulting from
                # operations between floating point numbers, since these are stored and handled differently in computer.
                if(round(sumi,4)!= 1.0 or (len(prob) != self.numSides)):
                    print(len(prob)," ",sumi)
                    raise Exception;
                else:

                    #self.probs is updated with new probabilities
                    self.probs = prob;
                    print(self.probs)

            except Exception:
                print('Invalid probability distribution', self.probs);
                return;

    #overloading print statement
    def __str__(self):
        return "Dice with {} faces and probability distribution {}".format(self.numSides,self.probs);

    #function to get the partition(and thus the face of the dice) corresponding to a randomly chosen value between 0 and 1;
    def findPart(self,val):
        for i in range (0,len(self.ls)):
            if self.ls[i] >= val:
                return i+1;

    def roll(self,num):
        # expected times a face turns up would be just equal to number of times dice is thrown * probability of that face to be turned up
        expected = list(map(lambda x: x*num,self.probs));
        self.ls = [self.probs[0]];
        for i in range(1,len(self.probs)):
            (self.ls).append((self.ls[i-1] + self.probs[i]));

        print(self.ls);
        # numTimes ith index stores the number of times ith vertex turn up when num times dixe is thrown (randomly)
        self.numTimes =[0]*len(self.ls);

        # we throw the dice num times, each time a random value in the interval(0,1) is chosen.
        # probability that it lies in any partition depends on the width of the partition( since we conider  Uniform distribution of random variables)
        # hence we find the partition and thus corresponding face value and increment number of occurences of that face value.

        for i in range (1,num+1):
            val = random.random();
            partition = self.findPart(val);
            self.numTimes[partition-1]= self.numTimes[partition-1]+1;

        # plotting barchart for expected and actual number of occurrences of each face when the dice is thrown n times.
        barWidth = 0.25;
        br1 = np.linspace(1,self.numSides,self.numSides);
        br2 = [x+barWidth for x in br1];

        plt.bar(br1,self.numTimes,color='b',width=barWidth,edgecolor='grey',label='Actual');
        plt.bar(br2,expected,color='r',width=barWidth,edgecolor='grey',label='Expected');
        plt.xticks([r+barWidth/2 for r in range(1,len(br1)+1)],br1);

        plt.title("Outcome of {} throws of a {}-faced dice".format(num,self.numSides));
        plt.xlabel('Sides');
        plt.ylabel('Occurences');

        plt.legend();
        plt.show();

if __name__ == "__main__":
    # making object of the class and plotting the actual-expected occurences roll graph for it
    d = Dice(5);
    d.setProb((0.2,0.1,0.4,0.2,0.1));
    print(d);
    d.roll(1000);


"""
Pedir al usuario que ingrese por teclado 2 números, si el primero es menor que el segundo imprimir
la resta entre el segundo y el primero, si el primero es mayor que el segundo imprimir la suma de ambos,
y si son iguales imprimir su producto.
"""

n = int(input("Ingrese un nro"))
m = int(input("Ingrese otro nro"))

if n < m:
    print(m - n)
elif n > m:
    print(n + m)
elif n == m:
    print(n * m)


def magic(n):
    m = []
    for i in range(n):
        m.append([0] * n)
    row, col = n - 1, n // 2
    for k in range(0, n * n):
        m[row][col], newRow, newCol = (k + 1), (row + 1) % n, (col + 1) % n
        if m[newRow][newCol] == 0:
            row, col = newRow, newCol
        else:
            row, col = row - 1, col
    return m

def show(m):
    for i in range(len(m)):
        for j in range(len(m)):
            print(("   " + str(m[i][j]))[-3:], end=" ")
        print()

import numpy as np

def np_is_magic(square):
    np_square = np.array(square)

    # Row sum
    row_sum = np.sum(np_square, axis=0)

    # Column sum
    col_sum = np.sum(np_square, axis=1)

    # Diagonal 1 sum
    d1_sum = np.trace(np_square)

    # Diagonal 2 sum
    d2_sum = np.trace(np.flip(np_square))

    # Checks if all elements are the same
    rows = all(ele == row_sum[0] for ele in row_sum)
    cols = all(ele == col_sum[0] for ele in col_sum)

    # Checks if diagonal sums are same as row sums
    d1 = d1_sum == row_sum[0]
    d2 = d2_sum == row_sum[0]

    # Checks if row, column, and both diagonal sums are equal
    if rows == cols == d1 == d2:
        print("Magic")
    else:
        print("Not magic")

def main():
    l = magic(5)
    show(l)
    np_is_magic(l)

if __name__ == "__main__":
    main()


#!/usr/bin/python
import smbus, time, sys, pygame, datetime
from pygame import mixer

# Get ready for some i2c stuff
bus = smbus.SMBus(1)
# Arduino i2c address
address = 0x04

def writeNumber(value):
    bus.write_byte(address, int(value))
    return -1

def readNumber():
    number = bus.read_byte(address)
    return number

pygame.init()
pygame.mixer.init()
#tone  = pygame.mixer.Sound("../FUN_sounds/Kenney_Sounds/1.ogg")

while True:
    # Rotary Digit  - MIGHT NOT NEED - TRY REMOVING AT SOME POINT
    #r_digit = "99"
    #writeNumber(r_digit)
    time.sleep(.6)
    number = readNumber()
    if number == 1:
        pygame.mixer.stop()
        print("Dialed 1 Received")
        number == 99;
        r_digit = "11"
        writeNumber(r_digit)
        tone = pygame.mixer.Sound("../FUN_sounds/Kenney_Sounds/1.ogg")
        tone.play()
        # time.sleep (20)
    if number == 55:
        print("off hook")
        number == 99;
        r_digit = "11"
        writeNumber(r_digit)
        tone = pygame.mixer.Sound("../FUN_sounds/dial_tone.ogg")
        tone.play()

    if number == 56:
        print("on hook")
        pygame.mixer.stop()
        number == 99;
        r_digit = "11"
        writeNumber(r_digit)
    if number == 2:
        print("Dialed 2 Received")
        number == 99;
        r_digit = "22"
        writeNumber(r_digit)
        tone = pygame.mixer.Sound("../FUN_sounds/Kenney_Sounds/2.ogg")
        tone.play()
    if number == 3:
        print("Dialed 3 Received")
        number == 99;
        r_digit = "33"
        writeNumber(r_digit)
        tone = pygame.mixer.Sound("../FUN_sounds/Kenney_Sounds/3.ogg")
        tone.play()
    if number == 4:
        print("Dialed 4 Received")
        number == 99;
        r_digit = "44"
        writeNumber(r_digit)
        # Dial Festival for Date
        mylist = []
        phone_time = datetime.datetime.now().strftime('%I Hours:%M Minutes: %p')
        mylist.append(phone_time)
        import subprocess
        at_tone = '"At the tone the time will be: "'
        #text = str(datetime.datetime.now().time())
        phone_time = str(mylist[0])
        filename = 'hello'
        file=open(filename,'w')
        file.write(at_tone)
        file.write(phone_time)
        file.close()
        subprocess.call('festival --tts '+filename, shell=True)

    if number == 5:
        print("Dialed 5 Received")
        number == 99;
        r_digit = "55"
        writeNumber(r_digit)
    #if number == 0:
    #    print("Dialed 0 Received")
    #    number == 99;
    #    r_digit = "55"
    #    writeNumber(r_digit)

    #print(number)


from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, Http404
from django.shortcuts import render, reverse
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.utils import timezone
from .models import Product, ProductVariant, Topping, Order, OrderItem
import random, string

class ProductVariantView:
    def __init__(
        self, variant, topping_no, small, large, onesize, is_addon, modal_name
    ):
        self.variant = variant
        self.topping_no = topping_no
        self.small = small
        self.large = large
        self.onesize = onesize
        self.is_addon = is_addon
        self.modal_name = modal_name

    def __str__(self):
        return f"{self.variant} - {self.onesize} - {self.small} - {self.large}"

class VariantPriceView:
    def __init__(self, id, price):
        self.id = id
        self.price = price

class ProductView:
    def __init__(self, name):
        self.name = name
        self.variants = []

    def add_variant(self, variant):
        self.variants.append(variant)

    def is_one_size(self):
        if len(self.variants) == 0:
            return True
        return self.variants[0].onesize != None

    def is_pizza(self):
        return "Pizza" in self.name

    def is_sub(self):
        return "Sub" in self.name

class Cart:
    def __init__(self, user):
        self.user = user
        self.items = []

    def addItem(self, item):
        existing_items = [
            i
            for i in self.items
            if i.variant.id == item.variant.id and i.toppings == item.toppings
        ]
        if len(existing_items) > 0:
            existing_items[0].quantity += 1
        else:
            self.items.append(item)

    def getTotal(self):
        total = sum(i.quantity for i in self.items)
        return total

    def getTotalPrice(self):
        total = sum(i.quantity * float(i.variant.price) for i in self.items)
        return total

class CartItem:
    def __init__(self, variant_id, topping_ids, addon_ids):
        self.variant = ProductVariant.objects.get(pk=variant_id)
        self.toppings = [
            topping for topping in Topping.objects.filter(pk__in=topping_ids)
        ]
        self.addons = [
            addon for addon in ProductVariant.objects.filter(pk__in=addon_ids)
        ]
        self.quantity = 1

    def unit_price(self):
        total_addon = 0
        for addon in self.addons:
            total_addon += addon.price
        return self.variant.price + total_addon

shopping_carts = {}

@login_required
def index(request):
    user = request.user
    product_name_list = []
    product_view_list = []

    productVariants = ProductVariant.objects.all()
    # get product
    for product in Product.objects.all():
        product_name = product.name

        if product_name in product_name_list:
            continue

        product_view = ProductView(product_name)
        variant_view_list = []

        # get variant
        for productVariant in productVariants:
            if productVariant.product.name == product_name:
                variant_name = productVariant.variant
                topping_no = productVariant.topping_no
                is_addon = productVariant.is_addon

                if variant_name in variant_view_list:
                    continue

                small_price = None
                large_price = None
                onesize_price = None
                modal_name = "#nonPizzaToppingModal"

                # get size
                for productVariant in productVariants:
                    if (
                        productVariant.product.name == product_name
                        and productVariant.variant == variant_name
                    ):
                        variant_id = productVariant.id
                        size = productVariant.size

                        if size == "sm":
                            small_price = VariantPriceView(
                                variant_id, productVariant.price
                            )

                        elif size == "lg":
                            large_price = VariantPriceView(
                                variant_id, productVariant.price
                            )
                        else:
                            onesize_price = VariantPriceView(
                                variant_id, productVariant.price
                            )

                        if product_view.is_pizza():
                            modal_name = "#pizzaToppingModal"
                        elif product_view.is_sub():
                            modal_name = "#subModal"

                    if (
                        small_price != None and large_price != None
                    ) or onesize_price != None:
                        break

                variant = ProductVariantView(
                    variant_name,
                    topping_no,
                    small_price,
                    large_price,
                    onesize_price,
                    is_addon,
                    modal_name,
                )

                variant_view_list.append(variant_name)
                product_view.add_variant(variant)

        product_name_list.append(product_name)
        product_view_list.append(product_view)

    topping_list = Topping.objects.all()
    cart = shopping_carts.get(request.user.id)
    if cart != None:
        total_items = cart.getTotal()
    else:
        total_items = 0

    context = {
        "products": product_view_list,
        "toppings": topping_list,
        "total_items": total_items,
    }
    return render(request, "orders/index.html", context)

@login_required
def add_to_cart(request):
    variant_id = request.POST.get("id", None)
    toppings = request.POST.get("toppings", None)
    topping_ids = [int(float(i)) for i in toppings.split(",")] if toppings else []
    addons = request.POST.get("addons", None)
    addon_ids = [int(float(i)) for i in addons.split(",")] if addons else []

    try:
        variant = ProductVariant.objects.get(pk=variant_id)
    except ProductVariant.DoesNotExist:
        raise Http404("Item does not exist")

    # validate number of toppings
    if len(topping_ids) != ProductVariant.objects.get(pk=variant_id).topping_no:
        raise Http404("Item does not exist")

    cart = shopping_carts.get(request.user.id)
    if cart == None:
        cart = Cart(request.user)
        shopping_carts[request.user.id] = cart

    item = CartItem(variant_id, topping_ids, addon_ids)
    cart.addItem(item)
    messages.success(
        request,
        f"{item.variant.product} - {item.variant.variant} has been added to your shopping cart",
    )

    return JsonResponse({"total": cart.getTotal()})

@login_required
def update_item_quantity(request):
    variant_id = request.POST.get("id", None)
    quantity = request.POST.get("quantity", None)
    cart = shopping_carts.get(request.user.id)
    updated_item = [item for item in cart.items if item.variant.id == int(variant_id)]
    updated_item[0].quantity = int(quantity)
    messages.success(
        request, f"Your shopping cart has been updated!",
    )

    return HttpResponse(status=204)

@login_required
def delete_cart(request):
    variant_id = request.POST.get("id", None)
    cart = shopping_carts.get(request.user.id)
    deleted_item = [item for item in cart.items if item.variant.id == int(variant_id)]
    cart.items.remove(deleted_item[0])
    messages.success(
        request, f"Successfully remove the item from cart!",
    )
    return HttpResponse(status=204)

@login_required
def get_cart(request):
    cart = shopping_carts.get(request.user.id)
    if cart == None:
        items = []
        total_items = 0
        total_price = 0
    else:
        items = cart.items
        total_items = cart.getTotal()
        total_price = cart.getTotalPrice()

    context = {"items": items, "total": total_price, "total_items": total_items}
    return render(request, "orders/cart.html", context)

@login_required
def place_order(request):
    cart = shopping_carts.get(request.user.id)
    # Insert order to database
    if cart == None:
        return HttpResponse("There's no items in your cart")
    else:
        ref_code = create_ref_code()
        new_order = Order.objects.create(
            user=request.user, ref_code=ref_code, ordered_date=timezone.now()
        )
        for item in cart.items:
            order_item = OrderItem.objects.create(
                item=item.variant, order=new_order, quantity=item.quantity
            )
            for topping in item.toppings:
                t = Topping.objects.get(pk=topping.id)
                order_item.toppings.add(t)
            for addon in item.addons:
                addon_variant = ProductVariant.objects.get(pk=addon.id)
                order_item.addons.add(addon_variant)

        shopping_carts.pop(request.user.id)
        messages.success(
            request,
            f"Your order has been received and will be processed as soon as possible",
        )

    return HttpResponseRedirect(reverse("order_summary", args=(new_order.id,)))

@login_required
def order_summary(request, order_id):
    items = OrderItem.objects.filter(order__user=request.user, order__id=order_id)
    try:
        order = Order.objects.get(pk=order_id)
    except Order.DoesNotExist:
        raise Http404("Order does not exist")
    total = order.get_total()
    ref_code = order.ref_code
    cart = shopping_carts.get(request.user.id)
    if cart == None:
        total_items = 0
    else:
        total_items = cart.getTotal()
    context = {
        "items": list(items),
        "total": total,
        "total_items": total_items,
        "ref_code": ref_code,
    }
    return render(request, "orders/order.html", context)

@login_required
def order_history(request):
    orders = Order.objects.filter(user=request.user)
    cart = shopping_carts.get(request.user.id)
    if cart == None:
        total_items = 0
    else:
        total_items = cart.getTotal()
    context = {"orders": list(orders), "total_items": total_items}
    return render(request, "orders/history.html", context)

def create_ref_code():
    return "".join(random.choices((string.ascii_lowercase + string.digits), k=10))


# 위상정렬_커리큘럼_try2
# 선수강의가 있을 수 있는 N개의 강의에 대해, 수강하기까지 걸리는 최소시간을 각각 출력
from collections import deque
from copy import deepcopy

n = int(input())
indegree = [0] * (n + 1)        # 위상 정렬
graph = [[] for i in range(n + 1)]
time = [0] * (n + 1)
q = deque()

for i in range(1, n + 1):
    data = list(map(int, input().split()))
    time[i] = data[0]       # 수강시간
    for x in data[1 : -1]:
        indegree[i] += 1
        graph[x].append(i)

for i in range(1, n + 1):
    if indegree[i] == 0:
        q.append(i)

result = deepcopy(time)
while q:
    now = q.popleft()

    for i in graph[now]:
        result[i] = max(result[i], result[now] + time[i])   # 이번 과목을 듣는 것과 안듣는 것의 최댓값
        indegree[i] -= 1        # 진입차수 감소

        if indegree[i] == 0:    # 새롭게 진입차수가 0이 된 과목 큐에 삽입
            q.append(i)

for i in range(1, n + 1):
    print(result[i])


#!/bin/python3
#CAN USE REDUCE FUNCTION ALSO!

import math
import os
import random
import re
import sys

#
# Complete the 'birthday' function below.
#
# The function is expected to return an INTEGER.
# The function accepts following parameters:
#  1. INTEGER_ARRAY s
#  2. INTEGER d
#  3. INTEGER m
#

def birthday(s, d, m):
    total = d
    end = m
    count = 0
    start =0

    while (end <= len(s)):
        if sum(s[start:end])== total:
            count+=1
        start += 1
        end += 1
    return count

if __name__ == '__main__':
    fptr = open(os.environ['OUTPUT_PATH'], 'w')

    n = int(input().strip())

    s = list(map(int, input().rstrip().split()))

    first_multiple_input = input().rstrip().split()

    d = int(first_multiple_input[0])

    m = int(first_multiple_input[1])

    result = birthday(s, d, m)

    fptr.write(str(result) + '\n')

    fptr.close()