pizza_example.py

# pizza_example.py

import random
import string
import pyceda
import pypizza
from pyceda.database import *

ceda = pyceda.rootnamespace.ceda
dt = pyceda.rootnamespace.dt
geom = pyceda.rootnamespace.geom
pizza = pyceda.rootnamespace.pizza

def printMap(name,m):
    print('  len({}) = {}'.format(name, len(m)))
    for key in m:
        print('  {}.has_key({}) = {}'.format(name, key, m.has_key(key)))
    for key in m:
        print('  {} in {} = {}'.format(key, name, key in m))
    for key in m.iterkeys():
        print('  {}[{}] = {}'.format(name, key, m[key]))
    for value in m.itervalues():
        print('  value: {}'.format(value))
    for item in m.iteritems():
        print('  item: {}'.format(item))
    for key,value in m.iteritems():
        print('  key: {}  value: {}'.format(key,value))

####################### DateTime

def selectDate():
    y = random.randint(2016,2017)
    m = random.randint(0,11)
    d = random.randint(1,28)
    return dt.TDate(Year=y,Month=m,Day=d)

def selectTime():
    h = random.randint(0,23)
    m = random.randint(0,59)
    return dt.TTime(Hour=h,Minute=m,Second=0)

def selectDateTime():
    return dt.TDateTime(selectDate(), selectTime())

def setDate(d):
    d.Year = random.randint(2016,2017)
    d.Month = random.randint(0,11)
    d.Day = random.randint(1,28)

def setTime(t):
    t.Hour = random.randint(0,23)
    t.Minute = random.randint(0,59)

def setDateTime(dt):
    setDate(dt.Date)
    setTime(dt.Time)

####################### TVehicleType

# Add all vehicle types to the given TPizzaDeliveryDatabase pdd
def addVehicleTypes(pdd):
    for s in [ 'Ford Fiesta', 'Mazda3', 'Kia Rio', 'Toyota Yaris', 'Honda Civic', 'Mitsubishi Lancer', 'Subaru Impreza', 'Volkswagen Passat']:
        id = len(pdd.VehicleTypes)+1
        pdd.VehicleTypes[id].Description = s

####################### TVehicle

def selectLicensePlateNumber():
    s = ''
    for i in range(3):
        s += random.choice(string.ascii_uppercase)
    s += '.'
    for i in range(3):
        s += str(random.randint(0,9))
    return s

def setVehicle(v):
    v.VehicleTypeId = random.randint(1,8)
    v.LicensePlateNumber = selectLicensePlateNumber()

####################### Address

def selectStreet():
    return random.choice([ 'Old Kent Road', 'Mayfair St', 'Oxford St', 'Regent St'])

def selectCity():
    return random.choice([ 'London', 'New York', 'Paris', 'Perth', 'Berlin'])

def selectState():
    return random.choice([ 'Alaska', 'New South Wales', 'Florida', 'California', 'Texas'])

def selectCountry():
    return random.choice([ 'Australia', 'USA', 'England', 'India'])

def selectZipCode():
    return random.randint(1000,9999)

def setAddress(a):
    a.Number = random.randint(1,50)
    a.Street = selectStreet()
    a.City = selectCity()
    a.ZipPostCode = selectZipCode()
    a.StateProvinceCounty = selectState()
    a.Country = selectCountry()

####################### Employee

def selectFirstName():
    return random.choice([ 'John', 'Janet', 'Kate', 'Rihanna', 'Peter', 'Greg'])

def selectLastName():
    return random.choice([ 'Smith', 'Matthews', 'Gates', 'Howard', 'Johnson'])

def selectPhoneNumber():
    s = ''
    for i in range(10):
        s += str(random.randint(0,9))
        if i == 3 or i == 6:
            s += ' '
    return s

def setEmployee(e):
    setAddress(e.Address)
    e.FirstName = selectFirstName()
    e.LastName = selectLastName()
    e.PhoneNumber = selectPhoneNumber()

# Add an employee to the given TPizzaDeliveryDatabase pdd
def addEmployee(pdd):
    i = len(pdd.Employees)
    setEmployee(pdd.Employees[i])

####################### Shape

def selectCircle():
    return pizza.TCircle(Radius=random.choice([100, 150, 250, 300]))

def selectRectangle():
    return pizza.TRectangle(Width=random.choice([100, 200]), Height=random.choice([200, 300]))

# Assign to s which is a variable of type TShape
def setShape(s):
    if random.randint(0,2) == 0:
        s.Circle = selectCircle()
    else:
        s.Rectangle = selectRectangle()

####################### Pizza

def selectTopping():
    return random.choice([ pizza.EBaseType.Thin, pizza.EBaseType.DeepPan])

def selectPizza():
    p = pizza.TOrderedPizza()
    setShape(p.Shape)
    p.BaseType = selectTopping()
    for i in range(random.randint(0,5)):
        p.ToppingIds.append(random.randint(0,10))
    return p

####################### TPizzaOrder

def selectDeliveryStatus():
    return random.choice([ pizza.EDeliveryStatus.Cooking, pizza.EDeliveryStatus.Delivering,  pizza.EDeliveryStatus.Completed,  pizza.EDeliveryStatus.Returned])

# Must be called by a thread that has opened a transaction on the database.
# Create an object of type TPizzaOrder.
def createPizzaOrder(id):
    order = pizza.TPizzaOrder.new(
        Id = id,
        CustomerId = random.randint(1,15),
        TakenByEmployeeId = random.randint(1,9),
        DeliveredByEmployeeId = random.randint(1,9),
        DeliveryStatus = selectDeliveryStatus(),
        VehicleId = random.randint(1,9),
        DateTimeOrderTaken = selectDateTime(),
        DateTimeOrderDelivered = selectDateTime(),
        TotalOrderPrice = random.randint(1000,5000)/100.0,
        Pizzas = [])
    for i in range(random.randint(0,3)):
        order.Pizzas.insert(i,selectPizza())
    return order

def insertSomeOrders(pdd, count):
    for i in range(count):
        pdd.Orders.insert(0, createPizzaOrder())

def appendSomeOrders(pdd, count):
    for i in range(count):
        pdd.Orders.append(createPizzaOrder())

# Add an order to the given TPizzaDeliveryDatabase pdd
def addOrder(pdd):
    id = len(pdd.Orders)
    pdd.Orders.append(createPizzaOrder(id))

# Replace last pizza in the ith order in the given TPizzaDeliveryDatabase pdd
def ReplaceLastPizzaInOrder(pdd,i):
    if pdd.Orders[i].Pizzas:
        pdd.Orders[i].Pizzas.pop()
        pdd.Orders[i].Pizzas.append(selectPizza())

# Print all the orders in the given TPizzaDeliveryDatabase pdd
def printOrders(pdd):
    print('Num orders = {}'.format(len(pdd.Orders)))
    for i in range(len(pdd.Orders)):
        order = pdd.Orders[i]
        print(''.format(order))

def printOrdersInTable(pdd):
    print(' Id  CustomerId        Name       Status')
    print('------------------------------------------')
    for i in range(len(pdd.Orders)):
        order = pdd.Orders[i]
        if order.CustomerId in pdd.Customers:
            c = pdd.Customers[order.CustomerId]
            print('{0:>4} {1:>10} {2:>17} {3:>6}'.format(order.Id, order.CustomerId, (str(c.FirstName) + ' ' + str(c.LastName)), order.DeliveryStatus))

####################### Customers

def selectEmail():
    return selectFirstName() + '.' + selectLastName() + '@gmail.com'

def selectPaymentMethod():
    return random.choice([ pizza.EPaymentMethod.Cash, pizza.EPaymentMethod.EftPos,  pizza.EPaymentMethod.CreditCard])

def setCustomer(c):
    setAddress(c.Address)
    c.FirstName = selectFirstName()
    c.LastName = selectLastName()
    c.PhoneNumber = selectPhoneNumber()
    c.Email = selectEmail()
    setDateTime(c.DateOfFirstOrder)
    c.PaymentMethod = selectPaymentMethod()

# Add a customer to the given TPizzaDeliveryDatabase pdd
def addCustomer(pdd):
    id = len(pdd.Customers)
    setCustomer(pdd.Customers[id])

####################### Toppings

def selectToppingPrice():
    return random.randint(100,200)/100.0

def selectToppingDescription():
    return random.choice([ 'Ham', 'Pineapple', 'Chicken', 'Jalapenos', 'Mushrooms', 'Zucchini', 'Garlic', 'Red peppers'])

def setTopping(t):
    t.Price = selectToppingPrice()
    t.Description = selectToppingDescription()

# Add a topping to the given TPizzaDeliveryDatabase pdd
def addTopping(pdd):
    id = len(pdd.Toppings)
    setTopping(pdd.Toppings[id])

# Returns a dictionary representation of the toppings
def getToppings(pdd):
    d = {}
    for id,topping in pdd.Toppings.iteritems():
        # The types of the topping fields are native python value types, so as required we are not
        # returning references to objects in the database (which can be an issue when done across a
        # transaction boundary).
        assert type(topping.Price) is float
        assert type(topping.Description) is str
        d[id] = (topping.Price, topping.Description)
    return d

####################### TPizzaDeliveryDatabase

def createPizzaDeliveryDatabase():
    pdd = pizza.TPizzaDeliveryDatabase.new()
    addVehicleTypes(pdd)
    for i in range(10):
        setVehicle(pdd.Vehicles[i+1])
    for i in range(10):
        addCustomer(pdd)
    return pdd

def printPizzaDeliveryDatabase(pdd):
    print(str(pdd))
    #printOrders(pdd)
    #printMap('pdd.Employees', pdd.Employees)

utRootKey = 'pizzadatabaseroot'

class PizzaDeliveryDatabase(Database):

    def __init__(self, path, createNew):
        Database.__init__(self)
        self.path = path
        self.createNew = createNew

    def __enter__(self):
        Database.open(self, self.path, self.createNew)
        self.bootstrapRootObject(utRootKey, lambda : createPizzaDeliveryDatabase())
        return self

    def __exit__(self, etype, value, tb):
        self.close()

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

for repeat in range(3):
    print('repeat = {}'.format(repeat))
    createNew = True if repeat==0 else False
    with PizzaDeliveryDatabase('mypizzadatabase', createNew) as db:
        pdd = db.rootObj       # The TPizzaDeliveryDatabase in the database

        if db.justCreated:
            print('Created new database')
        else:
            print('Opened existing database')

        with Txn(db):
            addCustomer(pdd)

        with Txn(db):
            addEmployee(pdd)

        with Txn(db):
            addTopping(pdd)

        with Txn(db):
            for i in range(10):
                addOrder(pdd)

        with Txn(db):
            ReplaceLastPizzaInOrder(pdd,0)

        with Txn(db):
            printOrdersInTable(pdd)
            #printPizzaDeliveryDatabase(pdd)

        with Txn(db):
            d = getToppings(pdd)
            print('toppings: {}'.format(d))

        # Cannot assign attribute FirstName of read-only pizza::TEmployee
        #with Txn(db):
        #    for id,e in pdd.Employees.iteritems():
        #        e.FirstName = 'Burt'

DataReplicationTest('mypizzadatabase', 'myreplicatedpizzadatabase', utRootKey, printPizzaDeliveryDatabase)