Initial Commit

This commit is contained in:
linkup11
2023-12-01 13:34:27 +01:00
commit b35b0e54be
7830 changed files with 1619698 additions and 0 deletions
View File
+2
View File
@@ -0,0 +1,2 @@
from django.contrib import admin
from .backend import *
+6
View File
@@ -0,0 +1,6 @@
from django.apps import AppConfig
class MygameConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'mygame'
View File
+163
View File
@@ -0,0 +1,163 @@
from django.db import models
from polymorphic.models import PolymorphicModel
# from .company import Company
from .worker import Worker
from .offer import Offer
from .order import Order
# Action und erbende Klassen
class Action(PolymorphicModel):
name = models.CharField(default="random Action", max_length=20)
actionmaker = models.ForeignKey("Company", default=1, on_delete=models.CASCADE)
def execute(self):
pass
def cancel(self):
pass
def addActionToCompany(self):
self.actionmaker.addAction(self)
def __str__(self):
return self.name
class ActionEmploy(Action):
worker = models.ForeignKey(Worker, default=1, on_delete=models.CASCADE)
@classmethod
def create(cls, worker, actionmaker):
# klassenobject erstellen
name = "Hiring " + worker.name
action = cls(name=name, worker=worker, actionmaker=actionmaker)
action.save()
# worker von market entferenen und action zu company hinzufügen
actionmaker.removeFromWorkermarket(worker)
action.addActionToCompany()
return action
def execute(self):
self.worker.setStatus(1)
self.worker.save()
self.actionmaker.workers.add(self.worker)
# Arbeiter zu Company hinzufügen
def cancel(self):
self.actionmaker.addToWorkermarket(self.worker)
class ActionUnemploy(Action):
worker = models.ForeignKey(Worker, null=True, blank=True, on_delete=models.CASCADE)
@classmethod
def create(cls, worker, actionmaker):
# klassenobject erstellen
name = "Firing " + worker.name
action = cls(name=name, worker=worker, actionmaker=actionmaker)
action.save()
# workerstatus anpassen und action zu company hinzufügen
actionmaker.workers.remove(worker)
action.addActionToCompany()
return action
def execute(self):
pass # self.worker.delete() hier das delete noch machbar machen
def cancel(self):
self.actionmaker.workers.add(self.worker)
class ActionOffer(Action):
order = models.ForeignKey(Order, default=1, on_delete=models.CASCADE)
amount = models.IntegerField(default=0)
@classmethod
def create(cls, order, amount, actionmaker):
# klassenobject erstellen
name = "Offer for " + order.name
action = cls(
name=name,
order=order,
amount=amount,
actionmaker=actionmaker,
)
action.save()
# order von market entfernen und action zu company hinzufügen
action.addActionToCompany()
return action
def execute(self):
self.order.setStatus(1)
self.order.save()
offer = Offer.objects.create(
company=self.actionmaker, amount=self.amount, order=self.order
)
self.order.offers.add(offer)
# Angebot einer Order auf OrderMarket vorlegen
def cancel(self):
# bleibt leer actually
pass
class ActionCancelOrder(Action):
order = models.ForeignKey(Order, default=1, on_delete=models.CASCADE)
@classmethod
def create(cls, order, actionmaker):
# klassenobject erstellen
name = "Cancel " + order.name
action = cls(
name=name,
order=order,
actionmaker=actionmaker,
)
action.save()
# action zu company hinzufügen
action.addActionToCompany()
return action
def execute(self):
self.actionmaker.calculateCustomerSatisfaction(-30)
self.order.cancelOrder()
self.order.delete()
def cancel(self):
# bleibt leer actually
pass
class ActionTrain(Action):
worker = models.ForeignKey(Worker, null=True, blank=True, on_delete=models.CASCADE)
trainskill = models.CharField(default="empty", max_length=50)
cost = models.IntegerField(default=1000)
@classmethod
def create(cls, worker, trainskill, actionmaker):
# klassenobject erstellen
name = "Train Worker " + worker.name
action = cls(
name=name,
worker=worker,
trainskill=trainskill,
actionmaker=actionmaker,
)
# worker locken status 3
worker.setStatus(3)
action.save()
# action zu company hinzufügen
action.addActionToCompany()
return action
def execute(self):
# Arbeiter in bestimmtem Skill verbesser und für eine runde locken
self.worker.improveAttribute(attribute=self.trainskill, amount=10)
self.worker.setLockedRounds(1)
# trainingskosten zahlen
self.actionmaker.addProfit(-self.cost)
def cancel(self):
self.worker.setStatus(1)
+46
View File
@@ -0,0 +1,46 @@
from django.db import models
import random
# attributeset für worker skills und order workload
class AttributeSet(models.Model):
experience = models.IntegerField(default=10)
reliability = models.IntegerField(default=10)
python = models.IntegerField(default=10)
javascript = models.IntegerField(default=10)
cpp = models.IntegerField(default=10)
management = models.IntegerField(default=10)
def __str__(self):
return "AttributeSet"
@classmethod
def createRandom(cls, median):
attributelist = []
for j in range(6):
randnumber = round(random.uniform(0.5, 1.5) * (median))
# if randnumber > 100:
# randnumber = 100
attributelist.append(randnumber)
attributeset = cls(
experience=attributelist[0],
reliability=attributelist[1],
python=attributelist[2],
javascript=attributelist[3],
cpp=attributelist[4],
management=attributelist[5],
)
attributeset.save()
return attributeset
def increase(self, amount, attribute):
if attribute in [
"experience",
"reliability",
"python",
"javascript",
"cpp",
"management",
]:
setattr(self, attribute, (getattr(self, attribute) + amount))
self.save()
+201
View File
@@ -0,0 +1,201 @@
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
import random
from mygame.backend.event import SpecialOrder
from .worker import Worker
from .order import Order
from .event import Event
from .action import *
# ACTION NOCH IMPORTIEREN?
# company die jeder spieler steuert
class Company(models.Model):
name = models.CharField(default="A company", max_length=20)
user = models.CharField(default="default User", max_length=20)
customersatisfaction = models.IntegerField(
default=100, validators=[MinValueValidator(0), MaxValueValidator(100)]
)
workersatisfaction = models.IntegerField(
default=100, validators=[MinValueValidator(0), MaxValueValidator(100)]
)
money = models.IntegerField(default=100000)
workermarket = models.ManyToManyField(Worker, related_name="workermarket")
actions = models.ManyToManyField("Action", blank=True)
workers = models.ManyToManyField(Worker, blank=True, related_name="workers")
orders = models.ManyToManyField(Order, blank=True)
events = models.ManyToManyField(Event, blank=True)
def __str__(self):
return self.name
def addProfit(self, profit):
self.money += profit
self.save()
def clearEvents(self):
for event in self.events.all():
# wenn specialorder ignoriert wurde -> penalty und removen (nicht löschen)
if isinstance(event, SpecialOrder):
for order in self.orders.all():
if order.specialorder == event:
event.handle(order=order, company=self, handle=False)
self.events.remove(event)
else:
event.delete()
def addEvent(self, event):
self.events.add(event)
self.save()
def getEvent(self, eventnumber, direction):
# wenn keine events gib leeres event
if not self.events.exists():
event = Event.createEmpty()
return (event, eventnumber)
# bei klick auf eventbutton immer erstes event zeigen
if eventnumber == 0 and direction == "default":
event = self.events.order_by("id")[eventnumber]
elif direction == "previous":
# wenn bei erstem element zurück dann letztes element zeigen
if eventnumber <= 0:
eventnumber = self.events.count() - 1
event = self.events.order_by("id")[eventnumber]
else:
eventnumber -= 1
event = self.events.order_by("id")[eventnumber]
elif direction == "next":
# wenn bei letztem element weiter dann erstes anzeigen
if eventnumber >= (self.events.count() - 1):
eventnumber = 0
event = self.events.order_by("id")[eventnumber]
else:
eventnumber += 1
event = self.events.order_by("id")[eventnumber]
return (event, eventnumber)
def addAction(self, action):
for existingaction in self.actions.all():
if action.name == existingaction.name:
self.cancelAction(existingaction.id)
self.actions.add(action)
def deleteAction(self, action):
self.actions.delete(action)
def calculateCustomerSatisfaction(self, number):
calc = self.customersatisfaction
calc += number
if calc < 0:
calc = 0
if calc > 100:
calc = 100
self.customersatisfaction = calc
self.save()
def calculateWorkerSatisfaction(self, number):
if (self.workersatisfaction + number) > 100:
self.workersatisfaction = 100
elif (self.workersatisfaction + number) < 0:
self.workersatisfaction = 0
else:
self.workersatisfaction += number
self.save()
def calculateAllWorkersHappyness(self, addhappyness):
for worker in self.workers.all():
worker.calculateHappyness(addhappyness)
def paySalary(self):
salarysum = 0
for worker in self.workers.all():
if self.money < salarysum:
worker.calculateHappyness(-50)
else:
salarysum += worker.salary
self.money -= salarysum
self.save()
def checkWorkerQuit(self):
threshhold = 55
for worker in self.workers.all():
if worker.happyness <= threshhold:
diff = threshhold - worker.happyness
randnum = random.randint(1, 100)
if 2 * diff > randnum:
event = Event.createWorkerQuit(
threshhold=threshhold,
workername=worker.name,
workerhappyness=worker.happyness,
)
self.addEvent(event)
worker.quitJob()
def calculateOrderWorkload(self):
for order in self.orders.all():
finished = order.calculateWorkload(self.workersatisfaction)
if finished:
order.finishOrder(self)
event = Event.createOrderFinished(
ordername=order.name, profit=str(order.profit)
)
self.events.add(event)
order.delete()
elif order.maxRounds == 0:
order.cancelOrder()
self.calculateCustomerSatisfaction(-30)
event = Event.createOrderFailed(ordername=order.name)
self.events.add(event)
order.delete()
def addOrder(self, order):
self.orders.add(order)
def deleteOrder(self, order):
self.orders.remove(order)
def addToWorkermarket(self, worker):
self.workermarket.add(worker)
def removeFromWorkermarket(self, worker):
self.workermarket.remove(worker)
def generateWorkermarket(self):
self.clearWorkermarket()
for x in range(5):
worker = Worker.createRandom()
self.addToWorkermarket(worker)
def clearWorkermarket(self):
for worker in self.workermarket.all():
if worker.status == 0:
worker.delete()
self.workermarket.clear()
# actions:
def cancelAction(self, id):
action = Action.objects.get(id=id)
action.cancel()
if action:
action.delete()
def actionEmploy(self, worker):
act = ActionEmploy.create(worker=worker, actionmaker=self)
return act
def actionUnemploy(self, worker):
act = ActionUnemploy.create(worker=worker, actionmaker=self)
return act
def actionOffer(self, order, amount):
act = ActionOffer.create(order=order, amount=amount, actionmaker=self)
return act
def actionCancelOrder(self, order):
act = ActionCancelOrder.create(order=order, actionmaker=self)
return act
def actionTrain(self, worker, trainskill):
act = ActionTrain.create(worker=worker, trainskill=trainskill, actionmaker=self)
return act
+147
View File
@@ -0,0 +1,147 @@
from django.db import models
from polymorphic.models import PolymorphicModel
import random
# EngineeringModel und erbende Klassen
class EngineeringModel(PolymorphicModel):
name = models.CharField(default="random EngineeringModel", max_length=30)
description = models.CharField(default="random description", max_length=200)
pros = models.CharField(default="random pro", max_length=100)
cons = models.CharField(default="random con", max_length=100)
# wird bei zuweisen des models ausgelöst
def recalculate(self, order, company):
pass
# wird bei workload berechnung ausgelöst, wenn workermodel nicht ordermodel
def penalty(self, worker, order):
worker.calculateHappyness(-5)
def bonus(self, worker, order):
pass
def __str__(self):
return self.name
def getPros(self):
return self.pros.split(",")
def getCons(self):
return self.cons.split(",")
class ModelV(EngineeringModel):
def recalculate(self, order, company):
# positives
# +10 workerSatisfaction +10 happyness
company.calculateAllWorkersHappyness(addhappyness=10)
company.calculateWorkerSatisfaction(number=10)
# +10 customerSatisfaction
company.calculateCustomerSatisfaction(10)
# negatives
# 1: extra work for SOPrototyp und SOChangeRequirement
# +10% workload
order.changeWorkload(1.1)
order.recalculated = True
order.save()
company.save()
class ModelSpiral(EngineeringModel):
def recalculate(self, order, company):
# positives
# 1: BONUS AUF SOPrototyp UND SOChangeRequirement
# +10 customerSatisfaciton
company.calculateCustomerSatisfaction(10)
# negatives
# 1: -10 happyness and workersatisfaction
company.calculateAllWorkersHappyness(addhappyness=-10)
company.calculateWorkerSatisfaction(number=-10)
# +10% workload
order.changeWorkload(1.1)
order.recalculated = True
order.save()
company.save()
class ModelWaterfall(EngineeringModel):
def recalculate(self, order, company):
# positives
# +10 workerSatisfaction +10 happyness
company.calculateAllWorkersHappyness(addhappyness=10)
company.calculateWorkerSatisfaction(number=10)
# -10% workload
order.changeWorkload(0.9)
# negatives
# 1: extra work for SOPrototyp und SOChangeRequirement
# -10 customerSatisfaction
company.calculateCustomerSatisfaction(-10)
order.recalculated = True
order.save()
company.save()
class ModelScrum(EngineeringModel):
def recalculate(self, order, company):
# positives
# 1: BONUS bei SOPrototyp und SOChangeRequirement
# 2: +20% if skilledModel of worker is scrum
# IN BONUS HIER UNTEN
# # negatives
# 1: random workload shift zwischen 1% und +20%
randnum = round(random.uniform(1.01, 1.2), 2)
order.changeWorkload(randnum)
# -40% auf skills wenn skilled model nicht scrum
# IN ORDER.CALCULATEWORKLOAD
order.recalculated = True
order.save()
company.save()
def bonus(self, worker, order):
ampnew = worker.amplifyer + 0.2
return ampnew
class ModelChaotic(EngineeringModel):
def recalculate(self, order, company):
# positives
# NIX
# negatives:
# +10% workload
order.changeWorkload(1.1)
# -20 workerSatisfaction -10 happyness
company.calculateAllWorkersHappyness(addhappyness=-10)
company.calculateWorkerSatisfaction(number=-20)
# extra work bei prototyp und changerequirement
order.recalculated = True
order.save()
company.save()
class ModelHeyJoe(EngineeringModel):
def recalculate(self, order, company):
# positives
# 1: BONUS AUF SOPrototyp UND SOChangeRequirement
# +30 customerSatisfaciton
company.calculateCustomerSatisfaction(30)
# negatives
# 1: -10 happyness and workersatisfaction
company.calculateAllWorkersHappyness(addhappyness=-15)
company.calculateWorkerSatisfaction(number=-15)
# +10% workload
order.changeWorkload(1.2)
order.recalculated = True
order.save()
company.save()
+310
View File
@@ -0,0 +1,310 @@
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
from polymorphic.models import PolymorphicModel
from .engineeringmodel import EngineeringModel
import random
# Event und erbende Klassen (specialOrder)
class Event(PolymorphicModel):
name = models.CharField(default="random Event", max_length=40)
description = models.CharField(default="Event description here", max_length=200)
@classmethod
def createEmpty(cls):
emptyEvent = cls(
name="Your E-Mails are empty",
description="You do not have E-Mails this round.",
)
emptyEvent.save()
return emptyEvent
@classmethod
def createOrderFailed(cls, ordername):
name = ordername + " canceled."
description = (
"Your order "
+ ordername
+ " ran out of rounds! The order was canceled and your customerSatisfaction decreased."
)
event = cls(
name=name,
description=description,
)
event.save()
return event
@classmethod
def createOrderFinished(cls, ordername, profit):
name = ordername + " finished."
description = (
"Your order "
+ ordername
+ " was completed! The profit of "
+ profit
+ " was added to your companys money."
)
event = cls(
name=name,
description=description,
)
event.save()
return event
@classmethod
def createWorkerQuit(cls, threshhold, workername, workerhappyness):
name = workername + " quit his job."
description = (
"Your worker "
+ workername
+ " quit his job due to his happyness falling to "
+ str(workerhappyness)
+ "! Falling below "
+ str(threshhold)
+ " will result in increasing chance for your worker to quit!"
)
event = cls(
name=name,
description=description,
)
event.save()
return event
@classmethod
def createSpecialOrderPenalty(cls, order):
name = "You ignored the Special Order for " + order.name
description = (
"You ignored the Special Order for the order "
+ order.name
+ ". Penalties have been applied! [-20 Customer Satisfaction; -20% Profit]"
)
event = cls(
name=name,
description=description,
)
event.save()
return event
@classmethod
def createSpecialOrderBonus(cls, order):
name = "You handled the Special Order for " + order.name
description = (
"You handled the Special Order for the order "
+ order.name
+ " in a flexible model. You received a bonus on your order!"
+ " [+10 Customer Satisfaction; +10 Worker Satisfaction; +20% Profit ; +10 happyness all Workers]"
)
event = cls(
name=name,
description=description,
)
event.save()
return event
@classmethod
def createSpecialOrderWrongModel(cls, order):
name = "You handled the Special Order for " + order.name
description = (
"You handled the Special Order for the order "
+ order.name
+ ", but you are working with an unflexible model! You let your workers work overtime to complete the customers wish."
+ " [+30 Workload on all Skills; -20 happyness all Workers; -10 Worker Satsifaction]"
)
event = cls(
name=name,
description=description,
)
event.save()
return event
class EventOfferAccepted(Event):
order = models.ForeignKey("Order", default=1, on_delete=models.CASCADE)
modelset = models.BooleanField(default=False)
def setModel(self, model):
self.order.setEngineeringmodel(model)
self.modelset = True
self.save()
class SpecialOrder(Event):
occuranceProbability = models.IntegerField(
default=100, validators=[MinValueValidator(0), MaxValueValidator(100)]
)
validModels = models.ManyToManyField(EngineeringModel, blank=True)
occured = models.BooleanField(default=False)
hint = models.CharField(default="no hint", max_length=100)
def getValidModels(self):
vmodels = []
for model in self.validModels.all():
vmodels.append(model.name)
return vmodels
def setDefaultValidModels(self):
self.validModels.add(EngineeringModel.objects.get(name="ModelScrum"))
self.validModels.add(EngineeringModel.objects.get(name="ModelSpiral"))
self.validModels.add(EngineeringModel.objects.get(name="ModelHeyJoe"))
def createHint(occuranceProbability):
if occuranceProbability <= 10:
hintlist = [
"The project is discussed completely from the beginning, and clear agreements are made regarding the requirements and scope of the project.",
"The customer is known to wish little interaction with its project partners and just wants to get the job done.",
"A tight budget and strict time management allows little changes within the project.",
"The company has emphasized the importance of precise planning and scope definition, indicating their intention to avoid unnecessary changes.",
"The client's primary focus is on efficiency and timely completion, suggesting they are unlikely to introduce substantial changes mid-project.",
"With a fixed project scope and well-defined milestones, the company seems committed to maintaining project stability.",
"Previous collaborations with the company reveal a preference for minimal modifications during the project execution phase.",
]
else:
hintlist = [
"Previous project collaborations with the firm have involved multiple change requests and additional features added throughout the development process.",
"The client has expressed a strong desire for flexibility and creativity in the project execution.",
"Given the dynamic nature of the industry they work in, it is likely that the company will request modifications to adapt to emerging trends.",
"The client has not yet finalized their longterm strategy, which means changes and updates to the project might be needed.",
"The company regularely takes user feedback, which might demand project alteration and updating.",
"The client has expressed an interest in prototyping certain features to explore different possibilities, which may result in the addition of new requirements.",
"The customer wishes for an agile project execution to have the option to get involved in the projects development.",
]
hint = random.choice(hintlist)
return hint
def calculateOccurance(self):
randnum = random.randint(1, 100)
if (self.occuranceProbability >= randnum) and not self.occured:
return True
else:
return False
def createOccuranceProbability():
# 50% chance dass es relativ wahrscheinlich/unwahrscheinlich ist das SO auftritt
randnum = random.randint(1, 2)
if randnum == 1:
# niedrige OP
occuranceProbability = random.randint(1, 5)
else:
# hohe OP
occuranceProbability = random.randint(30, 40)
return occuranceProbability
def occure(self, company):
if self.calculateOccurance():
company.events.add(self)
self.occured = True
self.save()
def handle(self, order, company, handle):
if order.engineeringModel.name in self.getValidModels():
self.bonus(order, company)
event = Event.createSpecialOrderBonus(order)
elif handle == True:
self.invest(order, company)
event = Event.createSpecialOrderWrongModel(order)
else:
self.penalty(order, company)
event = Event.createSpecialOrderPenalty(order)
company.events.remove(self)
company.events.add(event)
return event
def bonus(self, order, company):
company.calculateCustomerSatisfaction(20)
company.calculateWorkerSatisfaction(10)
order.profit *= 1.2
for worker in company.workers.all():
worker.calculateHappyness(10)
order.save()
company.save()
def penalty(self, order, company):
company.calculateCustomerSatisfaction(-20)
order.profit *= 0.8
order.save()
company.save()
def invest(self, order, company):
order.addWorkload(30)
for worker in company.workers.all():
worker.calculateHappyness(-20)
company.calculateWorkerSatisfaction(-10)
order.save()
company.save()
class SOPrototyp(SpecialOrder):
@classmethod
def createRandom(cls, ordername):
name = "Specialorder prototyp request from " + ordername
description = (
"Your customer for the order "
+ ordername
+ " wants you to produce a prototyp for them to review."
)
# hier random low <5% per round oder high < 40% per round
occuranceProbability = cls.createOccuranceProbability()
hint = cls.createHint(occuranceProbability=occuranceProbability)
specialorder = cls(
name=name,
description=description,
occuranceProbability=occuranceProbability,
hint=hint,
)
specialorder.save()
specialorder.setDefaultValidModels()
specialorder.save()
return specialorder
class SORegularIncrementUpdates(SpecialOrder):
@classmethod
def createRandom(cls, ordername):
name = "Specialorder regular incremental updates request from " + ordername
description = (
"Your customer for the order "
+ ordername
+ " wants to get regular updates on the increments of the project!"
)
# hier random low <5% per round oder high < 40% per round
occuranceProbability = cls.createOccuranceProbability()
hint = cls.createHint(occuranceProbability=occuranceProbability)
specialorder = cls(
name=name,
description=description,
occuranceProbability=occuranceProbability,
hint=hint,
)
specialorder.save()
specialorder.setDefaultValidModels()
specialorder.save()
return specialorder
class SOChangeRequirement(SpecialOrder):
@classmethod
def createRandom(cls, ordername):
name = "Specialorder change requirement request from " + ordername
description = (
"Your customer for the order "
+ ordername
+ " wants to change some requirements on your order. "
)
# hier random low <5% per round oder high < 40% per round
occuranceProbability = cls.createOccuranceProbability()
hint = cls.createHint(occuranceProbability=occuranceProbability)
specialorder = cls(
name=name,
description=description,
occuranceProbability=occuranceProbability,
hint=hint,
)
specialorder.save()
specialorder.setDefaultValidModels()
specialorder.save()
return specialorder
+300
View File
@@ -0,0 +1,300 @@
from django.db import models
from .names import WorkerNames, OrderNames
from .timer import Timer
from .timer import Timer
from .company import Company
from .order import Order
# from .action import Action
from .offer import Offer
from ..initialdatabase import InitialDatabase
from .engineeringmodel import (
ModelChaotic,
ModelScrum,
ModelSpiral,
ModelV,
ModelWaterfall,
ModelHeyJoe,
)
# Spielklasse kontrollier das gamegeschehen
class Game(models.Model):
name = models.CharField(default="Game", max_length=20)
gamemaster = models.CharField(max_length=20)
running = models.BooleanField(default=False)
participants = models.ManyToManyField(Company)
maxRounds = models.IntegerField(default=10)
currentRound = models.IntegerField(default=1)
ordermarket = models.ManyToManyField(Order)
actionpool = models.ManyToManyField("Action")
timer = models.ForeignKey(Timer, default=1, on_delete=models.CASCADE)
acceptedOffers = models.ManyToManyField(Offer, blank=True)
ordermarketsize = models.IntegerField(default=5)
def __str__(self):
return self.name
# Standard Datenbankeinträge generieren die hart codiert sind (in initialdatabase.py)
def initializeDatabase(self):
data = InitialDatabase()
self.createWorkernames(data)
self.createOrdernames(data)
self.createEngineeringmodels(data)
def createWorkernames(self, data):
for name in data.workernames:
WorkerNames.objects.get_or_create(name=name)
def createOrdernames(self, data):
for name in data.ordernames:
OrderNames.objects.get_or_create(name=name)
def createEngineeringmodels(self, data):
ModelV.objects.get_or_create(
name=data.engineeringmodelnames[0],
description=data.engineeringmodeldescription[0],
pros=data.engineeringmodelprocon[0][0],
cons=data.engineeringmodelprocon[0][1],
)
ModelSpiral.objects.get_or_create(
name=data.engineeringmodelnames[1],
description=data.engineeringmodeldescription[1],
pros=data.engineeringmodelprocon[1][0],
cons=data.engineeringmodelprocon[1][1],
)
ModelWaterfall.objects.get_or_create(
name=data.engineeringmodelnames[2],
description=data.engineeringmodeldescription[2],
pros=data.engineeringmodelprocon[2][0],
cons=data.engineeringmodelprocon[2][1],
)
ModelScrum.objects.get_or_create(
name=data.engineeringmodelnames[3],
description=data.engineeringmodeldescription[3],
pros=data.engineeringmodelprocon[3][0],
cons=data.engineeringmodelprocon[3][1],
)
ModelChaotic.objects.get_or_create(
name=data.engineeringmodelnames[4],
description=data.engineeringmodeldescription[4],
pros=data.engineeringmodelprocon[4][0],
cons=data.engineeringmodelprocon[4][1],
)
ModelHeyJoe.objects.get_or_create(
name=data.engineeringmodelnames[5],
description=data.engineeringmodeldescription[5],
pros=data.engineeringmodelprocon[5][0],
cons=data.engineeringmodelprocon[5][1],
)
# -----------------------------------------------------------------------------------
# Bearbeitung des Gameablaufs mit diesen Funktionen kontrollieren:
def startGame(self):
# klarmachen dass workernames ordernames engineeringmodels und spezialorders
# alle definiert sind -> sonst datenbankeinträge generieren
self.setDefault()
self.initializeDatabase()
# spiel auf running stellen
self.running = True
self.save()
# runde starten
self.startRound()
# timer starten
self.runTimer()
def setDefault(self):
self.currentRound = 1
self.save()
for company in self.participants.all():
for worker in company.workers.all():
worker.delete()
for order in company.orders.all():
order.delete()
company.money = 300000
company.customersatisfaction = 100
company.workersatisfaction = 100
company.save()
def endGame(self):
# game running False stellen
self.running = False
self.save()
def startRound(self):
# ordermarket generieren
self.generateOrdermarket()
# companys ihren workermarket generieren lassen
self.generateWorkermarket()
def processGameround(self):
# events von LETZTER RUNDE clearen()
self.clearEvents()
# arbeiter bezahlen
self.paySalary()
# schauen ob worker quittet (zufällig mit steigender wahrscheinlichkeit je niedriger)
self.checkWorkerQuit()
# companyOrder verbleibende Workload neu berechnen
self.calculateOrderWorkload()
# alle Aktionen ausführen und clearen
self.executeActions()
# Krankheit zufällig generieren
self.calculateSick()
# unlock locked workers wenn countdown auf 0; dann zähle countdown runter
self.countdownLockedWorkers()
# recalculate der models auf orders anwenden
self.modelsRecalculateOrders()
# SpecialOrders passieren lassen()
self.specialordersOccure()
# beste offer für jede order auf ordermarket rausfinden
self.calculateBestOffers()
# offers an beste berechnete company verteilen
self.distributeBestOffers()
# passive regeln anpassen
self.passiveGamerules()
# checken ob es letzte runde ist
gameend = self.checkLastRound()
# runde hochzählen
self.increaseRound()
# nächste Runde starten
self.startRound()
# gameende signalisieren
return gameend
# -----------------------------------------------------------------------------------
def passiveGamerules(self):
for company in self.participants.all():
company.calculateWorkerSatisfaction(2)
company.calculateCustomerSatisfaction(2)
for worker in company.workers.all():
worker.calculateHappyness(1)
# Spielexecution Funktionen die Funktionen zur Spielkontorlle implementieren
# adde 5 elemente zu ordermarket
def generateOrdermarket(self):
self.clearOrdermarket()
for x in range(self.ordermarketsize):
order = Order.createRandom()
self.addOrder(order)
def generateWorkermarket(self):
for company in self.participants.all():
company.generateWorkermarket()
def clearParticipants(self, username):
for player in self.participants.all():
# alle comapnys ausser gamemaster company kicken
if not (player.user == username):
self.participants.remove(player)
def clearEvents(self):
for company in self.participants.all():
company.clearEvents()
def callbackTimerCompleted(self):
gameend = self.processGameround()
if gameend:
self.timer.stop()
def runTimer(self):
self.timer.start(callback=self.callbackTimerCompleted)
def getRemainingTimer(self):
return self.timer.remainingtimer
def checkWorkerQuit(self):
for company in self.participants.all():
company.checkWorkerQuit()
def countdownLockedWorkers(self):
for company in self.participants.all():
for worker in company.workers.all():
# unlocken wenn locked und countdown = 0 und setze sick false
if worker.lockedRounds <= 0 and worker.status == 3:
worker.setStatus(1)
worker.setSick(False)
# countdown lockedRounds wenn größer 0
elif worker.lockedRounds > 0:
rounds = worker.lockedRounds - 1
worker.setLockedRounds(rounds)
def calculateSick(self):
for company in self.participants.all():
for worker in company.workers.all():
worker.calculateSick()
def executeActions(self):
for company in self.participants.all():
for action in company.actions.all():
action.execute()
for action in company.actions.all():
action.delete()
def calculateOrderWorkload(self):
for company in self.participants.all():
company.calculateOrderWorkload()
def calculateBestOffers(self):
for order in self.ordermarket.all():
bestoffer = order.calculateBestOffer()
self.acceptedOffers.add(bestoffer)
def modelsRecalculateOrders(self):
for company in self.participants.all():
for order in company.orders.all():
order.recalculate(company)
def distributeBestOffers(self):
for acceptedoffer in self.acceptedOffers.all():
acceptedoffer.order.setStatus(1)
self.ordermarket.remove(acceptedoffer.order)
acceptedoffer.company.addOrder(acceptedoffer.order)
acceptedoffer.offerAcceptedEvent()
# offers deleten da nicht mehr gebraucht
acceptedoffer.delete()
def specialordersOccure(self):
for company in self.participants.all():
for order in company.orders.all():
order.specialorder.occure(company=company)
def increaseRound(self):
self.currentRound += 1
self.save()
def checkLastRound(self):
if self.maxRounds <= self.currentRound:
self.endGame() # beende spiel
return True
return False
def addOrder(self, order):
self.ordermarket.add(order)
def removeOrder(self, order):
self.ordermarket.remove(order)
def clearOrdermarket(self):
for order in self.ordermarket.all():
if order.status == 0:
order.delete()
self.ordermarket.clear()
def paySalary(self):
for company in self.participants.all():
company.paySalary()
def createLeaderboard(self):
tuples = []
for company in self.participants.all():
tuples.append((company.money, company))
tuples = sorted(tuples, key=lambda x: x[0], reverse=True)
# companys aus den tuples ziehen
leaderboard = []
i = 1
for element in tuples:
leaderboard.append((i, element[1]))
i = i + 1
return leaderboard
+11
View File
@@ -0,0 +1,11 @@
from django.db import models
# Klassen für hartcodierte Datenbank:
# Namen Datenbank
class WorkerNames(models.Model):
name = models.CharField(default="no name", max_length=20)
class OrderNames(models.Model):
name = models.CharField(default="no name", max_length=20)
+25
View File
@@ -0,0 +1,25 @@
from django.db import models
from .event import EventOfferAccepted
# offer für orders
class Offer(models.Model):
company = models.ForeignKey("Company", default=1, on_delete=models.CASCADE)
amount = models.IntegerField(default=0)
order = models.ForeignKey("Order", default=1, on_delete=models.CASCADE)
def offerAcceptedEvent(self):
name = "Offer for " + self.order.name
description = (
"Your offer for the order "
+ self.order.name
+ " has been accepted!"
+ " You have "
+ str(self.order.maxRounds)
+ " rounds time to finish the order and claim your profit of "
+ str(self.order.profit)
)
offeracceptedevent = EventOfferAccepted.objects.create(
name=name, description=description, order=self.order
)
self.company.addEvent(offeracceptedevent)
+211
View File
@@ -0,0 +1,211 @@
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
import random
from .names import OrderNames
from .attributeset import AttributeSet
from .engineeringmodel import EngineeringModel
from .worker import Worker
from .offer import Offer
from .event import (
SpecialOrder,
SOChangeRequirement,
SORegularIncrementUpdates,
SOPrototyp,
)
# in attributeset einbauen?
attributelist = [
"experience",
"reliability",
"python",
"javascript",
"cpp",
"management",
]
# order zum abarbeiten
class Order(models.Model):
name = models.CharField(default="random order", max_length=20)
profit = models.IntegerField(default=1000)
status = models.IntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(1)]
)
maxRounds = models.IntegerField(
default=5, validators=[MinValueValidator(5), MaxValueValidator(100)]
)
requiredWorkload = models.ForeignKey(
AttributeSet, default=1, on_delete=models.CASCADE
)
engineeringModel = models.ForeignKey(
EngineeringModel, default=1, on_delete=models.DO_NOTHING, blank=True
)
assignedWorkers = models.ManyToManyField(Worker, blank=True)
offers = models.ManyToManyField(
Offer,
blank=True,
related_name="order_offers",
)
specialorder = models.ForeignKey(
SpecialOrder, default=1, on_delete=models.CASCADE, blank=True
)
recalculated = models.BooleanField(default=False)
def __str__(self):
return self.name
def getRandomSpecialorder(name):
randnum = random.randint(1, 3)
if randnum == 1:
specialorder = SOPrototyp.createRandom(name)
elif randnum == 2:
specialorder = SOChangeRequirement.createRandom(name)
else:
specialorder = SORegularIncrementUpdates.createRandom(name)
return specialorder
@classmethod
def createRandom(cls):
name = random.choice(OrderNames.objects.all()).name
profit = random.randint(40000, 100000)
maxRounds = round(random.uniform(0.7, 1.3) * (profit / 10000))
requiredWorkload = AttributeSet.createRandom(maxRounds * 13)
engineeringModel = EngineeringModel.objects.all().get(name="ModelChaotic")
specialorder = cls.getRandomSpecialorder(name)
order = cls(
name=name,
profit=profit,
maxRounds=maxRounds,
requiredWorkload=requiredWorkload,
engineeringModel=engineeringModel,
specialorder=specialorder,
)
order.save()
return order
def setStatus(self, status):
self.status = status
self.save()
def assignWorker(self, worker):
worker.setStatus(2)
self.assignedWorkers.add(worker)
def unassignWorker(self, worker):
worker.setStatus(1)
self.assignedWorkers.remove(worker)
def setEngineeringmodel(self, model):
self.engineeringModel = model
self.save()
def decreaseRounds(self):
self.maxRounds -= 1
self.save()
def recalculate(self, company):
if not self.recalculated:
self.engineeringModel.recalculate(order=self, company=company)
print("recalculated")
def calculateWorkload(self, workersatisfaction):
self.decreaseRounds()
finished = False
for worker in self.assignedWorkers.all():
if worker.skilledModels == self.engineeringModel:
if self.engineeringModel.name == "ModelScrum":
amplifyer = self.engineeringModel.bonus(worker=worker, order=self)
else:
amplifyer = worker.amplifyer
else:
self.engineeringModel.penalty(worker=worker, order=self)
if self.engineeringModel.name == "ModelScrum":
amplifyer = 0.6
else:
amplifyer = 1
# arbeit an order wenn nicht blockeirt
if worker.status != 3:
for attribute in attributelist:
newval = getattr(self.requiredWorkload, attribute) - (
getattr(worker.attributes, attribute)
* amplifyer
* (workersatisfaction * 0.01)
)
setattr(
self.requiredWorkload,
attribute,
max(0, newval), # 0 setzen wenn negativwert
)
self.requiredWorkload.save()
# prüfe ob alles abgearbeitet
finished = True
for attribute in attributelist:
if getattr(self.requiredWorkload, attribute) > 0:
finished = False
break
return finished
def changeWorkload(self, number):
for attribute in attributelist:
setattr(
self.requiredWorkload,
attribute,
getattr(self.requiredWorkload, attribute) * number,
)
self.requiredWorkload.save()
def addWorkload(self, number):
for attribute in attributelist:
setattr(
self.requiredWorkload,
attribute,
getattr(self.requiredWorkload, attribute) + number,
)
self.requiredWorkload.save()
def finishOrder(self, company):
company.addProfit(self.profit)
company.calculateCustomerSatisfaction(30)
company.save()
self.cancelOrder()
def addOffer(self, offer):
self.offers.add(offer)
def removeOffer(self, offer):
self.offers.remove(offer)
def checkOffer(self, amount):
if amount > (self.profit * 1.2) or amount < (self.profit * 0.8):
return False
else:
return True
def calculateBestOffer(self):
if self.offers.exists():
# Wenn offers vorhanden
bestoffer = (0, 0)
for offer in self.offers.all():
x = float(offer.company.customersatisfaction) / float(offer.amount)
if x >= bestoffer[0]:
bestoffer = (x, offer)
self.setProfit(offer.amount)
return bestoffer[1]
else:
# wenn keine offers
return
def cancelOrder(self):
for worker in self.assignedWorkers.all():
self.unassignWorker(worker)
self.save()
def setProfit(self, amount):
self.profit = amount
self.save()
+45
View File
@@ -0,0 +1,45 @@
from django.db import models
import threading
import time
# Timer mit Thread damit er seperat vom gamegeschehen läuft
class TimerThread(threading.Thread):
def __init__(self, timermodel, callback):
super(TimerThread, self).__init__()
self.timermodel = timermodel
self.callback = callback
def run(self):
self.timermodel.running = True
while self.timermodel.remainingtimer >= 0 and self.timermodel.running:
time.sleep(1)
self.timermodel.remainingtimer -= 1
self.timermodel.save()
if self.timermodel.remainingtimer <= 1:
# self.stop()
self.callback()
self.reset()
def reset(self):
self.timermodel.remainingtimer = self.timermodel.timer
self.timermodel.save()
def stop(self):
self.timermodel.running = False
self.reset()
# self.join()
class Timer(models.Model):
timer = models.IntegerField(default=60)
remainingtimer = models.IntegerField(default=60)
running = models.BooleanField(default=False)
def start(self, callback):
self.thread = TimerThread(self, callback)
self.thread.start()
def stop(self):
self.thread.stop()
+99
View File
@@ -0,0 +1,99 @@
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
import random
from .engineeringmodel import EngineeringModel, ModelChaotic
from .attributeset import AttributeSet
from .names import WorkerNames
# worker klasse
class Worker(models.Model):
name = models.CharField(default="random worker", max_length=20)
attributes = models.ForeignKey(AttributeSet, default=1, on_delete=models.CASCADE)
skilledModels = models.ForeignKey(
EngineeringModel, on_delete=models.CASCADE, blank=True
)
amplifyer = models.FloatField(
default=1, validators=[MinValueValidator(1.0), MaxValueValidator(2.0)]
)
salary = models.IntegerField(default=1000)
status = models.IntegerField(
default=0, validators=[MinValueValidator(0), MaxValueValidator(3)]
)
# status 0 = in workermarket; 1=in company; 2=wokring on order; 3=locked
lockedRounds = models.IntegerField(default=0, validators=[MinValueValidator(0)])
happyness = models.IntegerField(
default=100, validators=[MinValueValidator(0), MaxValueValidator(100)]
)
sick = models.BooleanField(default=False)
def __str__(self):
return self.name
@classmethod
def createRandom(cls):
name = random.choice(WorkerNames.objects.all()).name
attributes = AttributeSet.createRandom(20)
allmodels = EngineeringModel.objects.all()
allmodelsnochaotic = [
model for model in allmodels if not isinstance(model, ModelChaotic)
]
skilledModels = random.choice(allmodelsnochaotic)
if random.random() < 0.8:
value = round(random.uniform(1, 1.3), 1)
else:
value = round(random.uniform(1.3, 1.6), 1)
amplifyer = value
salary = round(amplifyer * 2500 * random.uniform(0.7, 1.3))
worker = cls(
name=name,
attributes=attributes,
skilledModels=skilledModels,
amplifyer=amplifyer,
salary=salary,
status=0,
)
worker.save()
return worker
def improveAttribute(self, attribute, amount):
self.attributes.increase(attribute=attribute, amount=amount)
def calculateHappyness(self, number):
if (self.happyness + number) > 100:
self.happyness = 100
elif (self.happyness + number) < 0:
self.happyness = 0
else:
self.happyness += number
self.save()
def quitJob(self):
self.delete()
def calculateSick(self):
if self.sick == False:
randnumber = random.randint(1, 100)
if randnumber <= 3:
self.setStatus(3)
self.setSick(True)
rounds = random.randint(1, 2)
self.setLockedRounds(rounds)
elif self.sick == True and self.lockedRounds < 0:
self.setSick(False)
self.setStatus(1)
def setStatus(self, status):
self.status = status
self.save()
def getStatus(self):
return self.status
def setLockedRounds(self, amount):
self.lockedRounds = amount
self.save()
def setSick(self, sickness):
self.sick = sickness
self.save()
+53
View File
@@ -0,0 +1,53 @@
import asyncio
from channels.generic.websocket import AsyncWebsocketConsumer
from .backend.game import Game
from channels.db import database_sync_to_async
class TimerConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.accept()
self.gameid = self.scope["url_route"]["kwargs"]["gameid"]
self.game = await self.getGame()
timer = await self.getRemainingTimer()
await self.send(text_data=str(timer))
self.timerTask = asyncio.ensure_future(self.timer(timer))
async def timer(self, timer):
await asyncio.sleep(1)
try:
while timer >= 0:
if self.game.running:
await self.send(text_data=str(timer))
timer -= 1
await asyncio.sleep(1)
else:
await self.send(text_data="game not started")
self.game = await self.getGame()
await asyncio.sleep(1)
except asyncio.CancelledError:
pass
finally:
self.game = await self.getGame()
if self.game.currentRound > self.game.maxRounds:
await self.send(text_data="endGame")
else:
await self.send(text_data="nextRound")
@database_sync_to_async
def getRemainingTimer(self):
return self.game.timer.remainingtimer
@database_sync_to_async
def getGame(self):
return Game.objects.get(id=self.gameid)
@database_sync_to_async
def processGameround(self, game):
gameend = game.processGameround()
async def receive(self, event):
pass
async def disconnect(self, event):
self.timerTask.cancel()
+22
View File
@@ -0,0 +1,22 @@
from django import forms
from django.core.validators import *
class LoginForm(forms.Form):
username = forms.CharField(
label="Username", min_length=4, max_length=30, widget=forms.TextInput
)
password = forms.CharField(
label="Password", min_length=4, max_length=30, widget=forms.PasswordInput
)
game_id = forms.CharField(label="Game ID", widget=forms.NumberInput)
create_join_game = forms.ChoiceField(
label="Create/Join Game",
choices=(("1", "Join"), ("2", "Create")),
)
class GamesettingsForm(forms.Form):
rounds = forms.CharField(label="set number of rounds:", required=False, widget=forms.NumberInput)
timer = forms.CharField(label="set roundtimer:", required=False, widget=forms.NumberInput)
ordermarketsize = forms.CharField(label="set ordermarket size:", required=False, widget=forms.NumberInput)
+313
View File
@@ -0,0 +1,313 @@
class InitialDatabase:
# Names generiert von chatgpt https://chat.openai.com/
# Workernames
workernames = [
"Emma",
"Mia",
"Hannah",
"Emilia",
"Lina",
"Ulma",
"Lena",
"Anna",
"Marie",
"Lea",
"Noah",
"Leon",
"Ben",
"Paul",
"Finn",
"Elias",
"Felix",
"Maximilian",
"Luis",
"Luca",
"Laura",
"Eva",
"Maja",
"Clara",
"Amelie",
"Isabella",
"Lara",
"Emily",
"Sarah",
"Charlotte",
"Alexander",
"Maximilian",
"Paul",
"Benjamin",
"Finn",
"Elias",
"Luis",
"Henry",
"Luca",
"Jakob",
"David",
"Niklas",
"Leon",
"Julian",
"Jonas",
"Tom",
"Tim",
"Simon",
"Moritz",
"Jan",
"Sofia",
"Luisa",
"Johanna",
"Mila",
"Liam",
"Oskar",
"Theo",
"Anton",
"Friedrich",
"Emil",
"Ida",
"Matilda",
"Greta",
"Frida",
"Mila",
"Lotta",
"Mina",
"Ella",
"Julia",
"Paula",
"Leonard",
"Karl",
"Erik",
"Johannes",
"Finn",
"Niklas",
"Max",
"Jonas",
"Jakob",
"Philipp",
"Hannah",
"Emilia",
"Clara",
"Lara",
"Isabella",
"Mia",
"Laura",
"Sophia",
"Lea",
"Marie",
]
# Ordernames
ordernames = [
"Online Shopping Platform",
"Fitness Tracking Mobile App",
"Social Media API",
"Customer Relationship Management System",
"Customer Support Chatbot",
"E-commerce Recommendation Engine",
"Web Scraping Tool",
"Payment Gateway Integration",
"Content Management System (CMS)",
"Real-time Analytics Dashboard",
"Task Management Application with Kanban Board",
"Retail Store Inventory Management System",
"Ticketing System for Customer Support",
"Sentiment Analysis Machine Learning Model",
"Blockchain-based Voting System",
"Location-based Restaurant Finder App",
"Calendar Scheduling Application",
"Document Management System",
"Virtual Reality (VR) Game",
"Multiplayer Online Game",
"Weather Forecasting Application",
"Stock Trading Platform",
"News Aggregator Website",
"Ride-sharing App with GPS Tracking",
"Movie Recommendation System",
"E-learning Platform",
"Music Streaming Service",
"Social Networking Platform",
"Video Conferencing Application",
"Movie Theater Ticket Reservation System",
"Automated Testing Framework for Web Applications",
"Business Card Scanning Mobile App",
"Secure Password Manager Application",
"Customer Review Sentiment Analysis Tool",
"Task Automation Script",
"Customer Feedback Management System",
"Recipe Recommendation App",
"Flight Booking System",
"Fraud Detection System for Financial Transactions",
"Online Auction Platform",
"Language Translation Tool",
"IT Support Ticketing System",
"Personal Finance Tracking Mobile App",
"Social Media Analytics Dashboard",
"Document Collaboration Platform",
"Task Tracking Application",
"Social Media Sentiment Analysis Tool",
"Book Recommendation System",
"E-commerce Platform with Inventory Management",
"Movie Review Sentiment Analysis Tool",
"Ride-hailing App",
"Content-based Music Playlist Recommendation System",
"Appointment Booking System for Healthcare Clinic",
"Secure Chat Application with End-to-End Encryption",
"Online Food Delivery Platform",
"Customer Feedback Sentiment Analysis Tool",
"Project Task Management System",
"News Recommendation Engine",
"Language Learning Mobile App",
"Travel Planning Application",
"AI-powered Virtual Assistant",
"Smart Home Automation System",
"Real Estate Listing Website",
"Restaurant Table Reservation System",
"Inventory Tracking Mobile App",
"Music Production Software",
"Event Management Platform",
"Online Course Marketplace",
"Expense Tracking Application",
"Job Recruitment Platform",
"Pet Adoption Website",
"Home Workout Mobile App",
"Stock Portfolio Management System",
"Social Media Influencer Analytics Tool",
"Food Recipe Sharing Platform",
"AI-based Image Recognition Software",
"Tourist Guide Mobile App",
"Cryptocurrency Exchange Platform",
"Language Proficiency Testing Software",
"Virtual Interior Design Application",
"Fitness Meal Planning App",
"Cloud Storage Service",
"Car Rental Booking System",
"Data Visualization Dashboard",
"Online Art Marketplace",
"Restaurant Review Aggregator",
"AI Chatbot for Legal Advice",
"Music Concert Ticket Booking App",
"Online Language Tutoring Platform",
"Virtual Job Interview Platform",
"Property Rental Management Software",
"Restaurant Menu Ordering App",
"AI-based Medical Diagnosis Tool",
"Online Wedding Planning Platform",
"Collaborative Code Editor",
"Online Therapy Platform",
"Home Energy Monitoring System",
"Sports League Management Software",
"AI-powered Resume Builder",
"Food Delivery Recommendation App",
"Online Marketplace for Handmade Crafts",
"Automated Email Marketing Platform",
]
# Engineeringmodel
engineeringmodelnames = [
"ModelV",
"ModelSpiral",
"ModelWaterfall",
"ModelScrum",
"ModelChaotic",
"ModelHeyJoe",
]
vmodeldesc = """The V-model uses a sequential approach with multiple phases, such as
specification, system modeling, component modeling, implementation, component testing, integration testing and validation. The
first four phases are constructive phases (creating code), while the last three phases concentrate on project quality and testing.
The name originates from the fact that the phases are often represented as a V, with the development phases (descending left side of the V)
facing the quality assurance (ascending right side of the V). Since each developmnet phase has a corresponding testing phase, assuring good project
quality is a basis of the V-model. Planning the project in closed phases also makes
the project easier to plan than than it would be with more flexible apporaches. The downside of the model is, that
preplanning phases will make change of requirements difficult and building the project from bottom up will make
prototyping hard to achieve."""
spiraldesc = """
The model spiral is an agile software engineering model that organizes the development
of a software product in multiple iterations. Each iteration implements a portion of the project
and creates a product prototype with more functionality than
the previous iteration, growing the product bigger with each step. Succesively improving
the project with each iteration makes finding errors early on in the project easy and naturaly
brings prototyped versions, which will make updating and communicating with customers easy. The downside
is, that this can lead to work redundancy, recoding functionalities and retesting, which makes
predicting the conclusion and costs of the project hard."""
waterfalldesc = """The model waterfall is a software engineering model that organizes
the workload in five phases: analysis, design, implementation, integration and production.
The phases will be worked through sequentially and going back phases is not intended. Using this
software engineering method is most succesful for short and well defined products, since it is
very unflexible and therefore it is hard to respond to customer requests. Due to its straight
forward nature with closed production phases it is easy for workers to work with and the production completion is
relatively predictable."""
scrumdesc = """Scrum is an agile software engineering model for incrementally and iteratively
developing software. Key elements within Scrum are short timewindows, designated to specific functionalities (Sprints),
planning tasks beforehand in a so called product backlog and daily meetings to keep every involved workers updated on
current problems and changes. This makes Scrum a highly flexible model with the ability to update customers frequently
and reach good project quality. The downside is, that workers have to get familiar with the working principles and
predicting the conclusion of a project can be hard due to the high flexibility."""
chaotidesc = """The chaotic model is equal to not choosing a model (default). It is not a model used in
softwareengineering, but signals that your workers will work uncoordinated. Working like this will make your workers more
insecure in their work and company."""
heyjoedesc = """The HeyJoe Model is an organizational method in which the manager organizes the team through
daily instructions. Users and customers communicate directly with the manager to access team members. Team members are
deployed flexibly to where they are most urgently needed, and their tasks, such as analysis and design, vary
depending on the daily instructions. The Model brings a lot of flexibility while working with customers, but workers
involved are working in a highly volatile work environment. Switching the tasks daily makes it hard to get a good workflow,
which increases the work needed to finish the whole project"""
engineeringmodeldescription = [
vmodeldesc,
spiraldesc,
waterfalldesc,
scrumdesc,
chaotidesc,
heyjoedesc,
]
vmodelprocon = [
# pros
"""-the preplanned phases give workers a good roadmap for their work [+10 Worker Satisfaction; +10 happynes all workers],
-multiple validation phases ensure a high quality project [+10 Customer Satisfaction]""",
# cons
"""-low flexibility due to preplanned phases [extra work for SPECIAL ORDERS],
-the emphasise on testing and validating each development step can cause extra workload [+10% workload]""",
]
spiralprocon = [
# pros
"""-high flexibility and regular prototyping within production [bonus on SPECIAL ORDERS],
-easy customer involvement and feedback through the production process [+10 Customer Satisfaction]""",
# cons
"""-multiple iterations can lead to work redundancy and recoding functionalities [+10% workload],
-workers will be unhappy with the redundant work [-10 Worker Satisfaction; -10 happynes all workers]""",
]
waterfallprocon = [
# pros
"""-workers appreciate the easy usage and predictability [+10 Worker Satisfaction; +10 happynes all workers],
-straight forward planning and clear responsibilities [-10% workload]""",
# cons
"""-low flexibility due to preplanned phases [extra work for SPECIAL ORDERS],
-low customer involvement and late feedback [-10 Customer Satisfaction]""",
]
scrumprocon = [
# pros
"""-high flexibility and iterative work in closed production iterations (sprints) [bonus on SPECIAL ORDERS],
-workers familiar with Scrum work efficiently with it [+20% on skills if skilled model is Scrum]""",
# cons
"""-the high flexibility makes predicting project conclusion hard [random workload shift between 1% and +20%],
-workers not familiar with scrum are overthrown by the new structure [-40% on skills if skilled model is NOT ModelScrum]""",
]
chaoticprocon = [
# pros
"""this model doesnt bring positives""",
# cons
"""-workers dont like volatility in their workplace [-20 Worker Satisfaction],
-missing structure leads to inefficient work [+10% workload],
-workers are not prepared for flexibility [extra work for SPECIAL ORDERS]""",
]
heyjoeprocon = [
# pros
"""-due to tasks varying every day, flexibility in project inkrementation is easy [bonus on SPECIAL ORDERS],
-customers like the easy way for them to influence the project by contacting the manager [+30 Customer Satisfaction]""",
# cons
"""-workers dislike the high volatility in their daily work [-15 Worker Satisfaction; -15 happynes all workers],
-Switching tasks daily leads to more workload due to workers having to adjust to new tasks [+20% workload]""",
]
engineeringmodelprocon = [
vmodelprocon,
spiralprocon,
waterfallprocon,
scrumprocon,
chaoticprocon,
heyjoeprocon,
]
+372
View File
@@ -0,0 +1,372 @@
# Generated by Django 4.1.7 on 2023-08-03 10:31
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
]
operations = [
migrations.CreateModel(
name='Action',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='random Action', max_length=20)),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
),
migrations.CreateModel(
name='AttributeSet',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('experience', models.IntegerField(default=10)),
('reliability', models.IntegerField(default=10)),
('python', models.IntegerField(default=10)),
('javascript', models.IntegerField(default=10)),
('cpp', models.IntegerField(default=10)),
('management', models.IntegerField(default=10)),
],
),
migrations.CreateModel(
name='Company',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='A company', max_length=20)),
('user', models.CharField(default='default User', max_length=20)),
('customersatisfaction', models.IntegerField(default=100, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(100)])),
('workersatisfaction', models.IntegerField(default=100, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(100)])),
('money', models.IntegerField(default=100000)),
('actions', models.ManyToManyField(blank=True, to='mygame.action')),
],
),
migrations.CreateModel(
name='EngineeringModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='random EngineeringModel', max_length=30)),
('description', models.CharField(default='random description', max_length=200)),
('pros', models.CharField(default='random pro', max_length=100)),
('cons', models.CharField(default='random con', max_length=100)),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
),
migrations.CreateModel(
name='Event',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='random Event', max_length=40)),
('description', models.CharField(default='Event description here', max_length=200)),
('polymorphic_ctype', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
),
migrations.CreateModel(
name='Offer',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('amount', models.IntegerField(default=0)),
('company', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.company')),
],
),
migrations.CreateModel(
name='OrderNames',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='no name', max_length=20)),
],
),
migrations.CreateModel(
name='Timer',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timer', models.IntegerField(default=60)),
('remainingtimer', models.IntegerField(default=60)),
('running', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='WorkerNames',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='no name', max_length=20)),
],
),
migrations.CreateModel(
name='ModelChaotic',
fields=[
('engineeringmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.engineeringmodel')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.engineeringmodel',),
),
migrations.CreateModel(
name='ModelScrum',
fields=[
('engineeringmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.engineeringmodel')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.engineeringmodel',),
),
migrations.CreateModel(
name='ModelSpiral',
fields=[
('engineeringmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.engineeringmodel')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.engineeringmodel',),
),
migrations.CreateModel(
name='ModelV',
fields=[
('engineeringmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.engineeringmodel')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.engineeringmodel',),
),
migrations.CreateModel(
name='ModelWaterfall',
fields=[
('engineeringmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.engineeringmodel')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.engineeringmodel',),
),
migrations.CreateModel(
name='SpecialOrder',
fields=[
('event_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.event')),
('occuranceProbability', models.IntegerField(default=100, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(100)])),
('occured', models.BooleanField(default=False)),
('hint', models.CharField(default='no hint', max_length=100)),
('validModels', models.ManyToManyField(blank=True, to='mygame.engineeringmodel')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.event',),
),
migrations.CreateModel(
name='Worker',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='random worker', max_length=20)),
('amplifyer', models.FloatField(default=1, validators=[django.core.validators.MinValueValidator(1.0), django.core.validators.MaxValueValidator(2.0)])),
('salary', models.IntegerField(default=1000)),
('status', models.IntegerField(default=0, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(3)])),
('lockedRounds', models.IntegerField(default=0, validators=[django.core.validators.MinValueValidator(0)])),
('happyness', models.IntegerField(default=100, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(100)])),
('sick', models.BooleanField(default=False)),
('attributes', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.attributeset')),
('skilledModels', models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to='mygame.engineeringmodel')),
],
),
migrations.CreateModel(
name='Order',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='random order', max_length=20)),
('profit', models.IntegerField(default=1000)),
('status', models.IntegerField(default=0, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(1)])),
('maxRounds', models.IntegerField(default=5, validators=[django.core.validators.MinValueValidator(5), django.core.validators.MaxValueValidator(100)])),
('recalculated', models.BooleanField(default=False)),
('assignedWorkers', models.ManyToManyField(blank=True, to='mygame.worker')),
('engineeringModel', models.ForeignKey(blank=True, default=1, on_delete=django.db.models.deletion.DO_NOTHING, to='mygame.engineeringmodel')),
('offers', models.ManyToManyField(blank=True, related_name='order_offers', to='mygame.offer')),
('requiredWorkload', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.attributeset')),
('specialorder', models.ForeignKey(blank=True, default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.specialorder')),
],
),
migrations.AddField(
model_name='offer',
name='order',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.order'),
),
migrations.CreateModel(
name='Game',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(default='Game', max_length=20)),
('gamemaster', models.CharField(max_length=20)),
('maxRounds', models.IntegerField(default=10)),
('currentRound', models.IntegerField(default=1)),
('ordermarketsize', models.IntegerField(default=5)),
('acceptedOffers', models.ManyToManyField(blank=True, to='mygame.offer')),
('actionpool', models.ManyToManyField(to='mygame.action')),
('ordermarket', models.ManyToManyField(to='mygame.order')),
('participants', models.ManyToManyField(to='mygame.company')),
('timer', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.timer')),
],
),
migrations.AddField(
model_name='company',
name='events',
field=models.ManyToManyField(blank=True, to='mygame.event'),
),
migrations.AddField(
model_name='company',
name='orders',
field=models.ManyToManyField(blank=True, to='mygame.order'),
),
migrations.AddField(
model_name='company',
name='workermarket',
field=models.ManyToManyField(related_name='workermarket', to='mygame.worker'),
),
migrations.AddField(
model_name='company',
name='workers',
field=models.ManyToManyField(blank=True, related_name='workers', to='mygame.worker'),
),
migrations.AddField(
model_name='action',
name='actionmaker',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.company'),
),
migrations.AddField(
model_name='action',
name='polymorphic_ctype',
field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='polymorphic_%(app_label)s.%(class)s_set+', to='contenttypes.contenttype'),
),
migrations.CreateModel(
name='SOChangeRequirement',
fields=[
('specialorder_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.specialorder')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.specialorder',),
),
migrations.CreateModel(
name='SOPrototyp',
fields=[
('specialorder_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.specialorder')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.specialorder',),
),
migrations.CreateModel(
name='SORegularIncrementUpdates',
fields=[
('specialorder_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.specialorder')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.specialorder',),
),
migrations.CreateModel(
name='EventOfferAccepted',
fields=[
('event_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.event')),
('modelset', models.BooleanField(default=False)),
('order', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.order')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.event',),
),
migrations.CreateModel(
name='ActionUnemploy',
fields=[
('action_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.action')),
('worker', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mygame.worker')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.action',),
),
migrations.CreateModel(
name='ActionTrain',
fields=[
('action_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.action')),
('trainskill', models.CharField(default='empty', max_length=50)),
('cost', models.IntegerField(default=1000)),
('worker', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mygame.worker')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.action',),
),
migrations.CreateModel(
name='ActionOffer',
fields=[
('action_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.action')),
('amount', models.IntegerField(default=0)),
('order', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.order')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.action',),
),
migrations.CreateModel(
name='ActionEmploy',
fields=[
('action_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.action')),
('worker', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.worker')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.action',),
),
migrations.CreateModel(
name='ActionCancelOrder',
fields=[
('action_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.action')),
('order', models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='mygame.order')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.action',),
),
]
+18
View File
@@ -0,0 +1,18 @@
# Generated by Django 4.1.7 on 2023-09-11 07:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mygame', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='game',
name='running',
field=models.BooleanField(default=False),
),
]
+25
View File
@@ -0,0 +1,25 @@
# Generated by Django 4.1.7 on 2023-10-20 14:14
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mygame', '0002_game_running'),
]
operations = [
migrations.CreateModel(
name='ModelHeyJoe',
fields=[
('engineeringmodel_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='mygame.engineeringmodel')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('mygame.engineeringmodel',),
),
]
View File
+1
View File
@@ -0,0 +1 @@
from .backend import game
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r"^mygame/company/(?P<gameid>\d+)/$", consumers.TimerConsumer.as_asgi())
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

+423
View File
@@ -0,0 +1,423 @@
{% extends "mygame/company.html" %} {% block content %}
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded text-danger"
>
Action: {{viewedaction.name}}
</h1>
{%if viewedaction.order%}
<!-- Order offer -->
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Workload
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Required Skill</th>
<th scope="col">Workload</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">experience</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-experience"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.order.requiredWorkload.experience}}%"
>
{{viewedaction.order.requiredWorkload.experience}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">reliability</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-reliability"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.order.requiredWorkload.reliability}}%"
>
{{viewedaction.order.requiredWorkload.reliability}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">python</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-python"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.order.requiredWorkload.python}}%"
>
{{viewedaction.order.requiredWorkload.python}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">javascript</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-javascript"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.order.requiredWorkload.javascript}}%"
>
{{viewedaction.order.requiredWorkload.javascript}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">cpp</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-cpp"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.order.requiredWorkload.cpp}}%"
>
{{viewedaction.order.requiredWorkload.cpp}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">management</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.order.requiredWorkload.management}}%"
>
{{viewedaction.order.requiredWorkload.management}}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Attributes
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Attribute</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
{%if viewedaction.amount%}
<tr>
<th scope="row" class="fs-5 text-danger">Offered Amount</th>
<td class="fs-5 text-danger">{{viewedaction.amount}}</td>
</tr>
{%endif%}
<tr>
{%if viewedaction.amount%}
<th scope="row">Maximum Rounds</th>
{%else%}
<th scope="row">Rounds left</th>
{%endif%}
<td>{{viewedaction.order.maxRounds}}</td>
</tr>
{%if viewedaction.order.status == 1%}
<tr>
<th scope="row">Engineeringmodel</th>
<td>{{viewedaction.order.engineeringModel}}</td>
</tr>
{% endif%}
<tr>
<th scope="row">Customer Description</th>
<td>{{viewedaction.order.specialorder.hint}}</td>
</tr>
</tbody>
</table>
</div>
{%endif%} {%if viewedaction.trainskill%}
<!-- Training -->
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Training
</h2>
<div class="m-2">
<table class="table">
<tbody>
<tr>
<th scope="row">Worker</th>
<td>{{viewedaction.worker.name}}</td>
</tr>
<tr>
<th scope="row">Training Skill</th>
<td>{{viewedaction.trainskill}}</td>
</tr>
<tr>
<th scope="row">Cost</th>
<td>{{viewedaction.cost}}</td>
</tr>
</tbody>
</table>
</div>
{%endif%}{%if viewedaction.worker%}
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Skills
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Skill</th>
<th scope="col">Strength</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">experience</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-experience"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.worker.attributes.experience}}%"
>
{{viewedaction.worker.attributes.experience}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">reliability</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-reliability"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.worker.attributes.reliability}}%"
>
{{viewedaction.worker.attributes.reliability}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">python</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-python"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.worker.attributes.python}}%"
>
{{viewedaction.worker.attributes.python}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">javascript</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-javascript"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.worker.attributes.javascript}}%"
>
{{viewedaction.worker.attributes.javascript}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">cpp</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-cpp"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.worker.attributes.cpp}}%"
>
{{viewedaction.worker.attributes.cpp}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">management</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.worker.attributes.management}}%"
>
{{viewedaction.worker.attributes.management}}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
{%if not viewedaction.trainskill%}
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Attributes
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Attribute</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Skilled Model</th>
<td>{{viewedaction.worker.skilledModels}}</td>
</tr>
<tr>
<th scope="row">Amplifyer</th>
<td>{{viewedaction.worker.amplifyer}}</td>
</tr>
<tr>
<th scope="row">Salary</th>
<td>{{viewedaction.worker.salary}}</td>
</tr>
<tr>
<th scope="row">Happyness</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedaction.worker.happyness}}%"
>
{{viewedaction.worker.happyness}}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
{%endif%} {%endif%}
<form
action="{% url 'companyAction' gameid=game.id username=user.username actionid=viewedaction.id %}"
method="post"
>
{% csrf_token %}
<div class="d-grid gap-2">
<input
class="btn btn-danger m-2"
type="submit"
value="cancel"
id="cancel"
name="action"
/>
</div>
</form>
{% endblock %}
+249
View File
@@ -0,0 +1,249 @@
{% extends "mygame/company.html" %} {% block content %}
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded"
>
Assign Workers: {{assignorder.name}}
</h1>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Workload
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Required Skill</th>
<th scope="col">Workload</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">experience</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-experience"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{assignorder.requiredWorkload.experience}}%"
>
{{assignorder.requiredWorkload.experience}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">reliability</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-reliability"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{assignorder.requiredWorkload.reliability}}%"
>
{{assignorder.requiredWorkload.reliability}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">python</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-python"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{assignorder.requiredWorkload.python}}%"
>
{{assignorder.requiredWorkload.python}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">javascript</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-javascript"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{assignorder.requiredWorkload.javascript}}%"
>
{{assignorder.requiredWorkload.javascript}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">cpp</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-cpp"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{assignorder.requiredWorkload.cpp}}%"
>
{{assignorder.requiredWorkload.cpp}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">management</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{assignorder.requiredWorkload.management}}%"
>
{{assignorder.requiredWorkload.management}}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Attributes
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Relevant Attribute</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Remaining Rounds</th>
<td>{{assignorder.maxRounds}}</td>
</tr>
<tr>
<th scope="row">Model</th>
<td>{{assignorder.engineeringModel}}</td>
</tr>
</tbody>
</table>
</div>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Assign
</h2>
<form
class="m-2"
action="{% url 'companyOrder' gameid=game.id username=user.username orderid=assignorder.id %}"
method="post"
>
{% csrf_token %}
<table class="table">
<thead>
<tr>
<th scope="col">Unassigned Workers</th>
<th scope="col">Assigned Workers</th>
</tr>
</thead>
<tbody>
<tr>
<td>
{% for worker in company.workers.all %} {%if worker.sick == True%}
<div class="m-2">
<label for="assign {{worker.id}}">
{{worker.name}}({{worker.skilledModels}})</label
>
<input
type="checkbox"
id="assign {{worker.id}}"
name="assign {{worker.id}}"
value="{{worker.id}}"
disabled
/>
</div>
{% elif worker.status == 1 %}
<div class="m-2">
<label for="assign {{worker.id}}">
{{worker.name}} ({{worker.skilledModels}})</label
>
<input
type="checkbox"
id="assign {{worker.id}}"
name="assign {{worker.id}}"
value="{{worker.id}}"
/>
</div>
{% endif %} {% endfor %}
</td>
<td>
{% for worker in assignorder.assignedWorkers.all %}
<div class="m-2">
<label for="{{worker.id}}">
{{worker.name}} ({{worker.skilledModels}})</label
>
<input
type="checkbox"
id="unassign {{worker.id}}"
name="unassign {{worker.id}}"
value="{{worker.id}}"
/>
</div>
{% endfor %}
</td>
</tr>
</tbody>
</table>
<div class="d-grid gap-2">
<input
class="btn btn-success m-2"
type="submit"
name="action"
id="save assignment"
value="save assignment"
/>
</div>
</form>
{% endblock %}
+559
View File
@@ -0,0 +1,559 @@
{%load static%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
.container-fluid {
height: 75%;
display: flex;
flex-direction: row;
}
.col-coloring {
background-color: lightgray;
}
.bottom-row {
background-color: #333;
color: white;
height: 20%;
}
.header {
background-color: #333;
color: white;
justify-content: space-evenly;
height: 5%;
width: 100%;
}
.viewlinker {
text-decoration: none;
color: black;
}
.hovering {
}
.hovering:hover {
background-color: grey;
}
</style>
<title>Company</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css"
/>
</head>
<body>
<script>
var currentURL = window.location.href;
var urlSplit = currentURL.split("/");
var indexCompany = urlSplit.indexOf("company");
var gameid = urlSplit[indexCompany + 1];
var url =
"ws://" + window.location.host + "/mygame/company/" + gameid + "/";
var socket = new WebSocket(url);
socket.onmessage = function (event) {
if (event.data === "nextRound") {
document.getElementById("nextRoundForm").submit();
} else if (event.data === "endGame") {
document.getElementById("endGameForm").submit();
} else {
var timerDiv = document.getElementById("timer");
timerDiv.innerHTML = event.data;
}
};
socket.onopen = function () {
console.log("Socket opened");
};
socket.onclose = function () {
console.log("Socket closed");
};
socket.onerror = function (error) {
console.log("Socket error:");
};
</script>
<div
class="header row align-items-center text-center justify-content-evenly g-0"
>
<div class="col-md">{{company.name}}</div>
<div class="col-md">
<form
action="{% url 'companyEvent' gameid=game.id username=user.username eventnumber=0%}"
method="get"
>
{% csrf_token %}
<input
class="btn btn-primary"
type="submit"
value="E-Mails"
id="viewgamerules"
name="action"
/>
</form>
</div>
<div class="col-md">Money: {{company.money}}</div>
<div class="col-md">
Customer Satisfaction: {{company.customersatisfaction}}
</div>
<div class="col-md">
Worker Satisfaction: {{company.workersatisfaction}}
</div>
<div class="col-md">Round: {{game.currentRound}}/{{game.maxRounds}}</div>
{% if game.running == True%}
<div class="timer col-md" id="timer">Timer:</div>
{% else %}
<div class="col-md">Game didn't start yet</div>
{%endif%}
</div>
<form
id="nextRoundForm"
action="{% url 'companyEvent' gameid=game.id username=user.username eventnumber=0%}"
method="get"
style="display: none"
>
{% csrf_token %}
</form>
<form
id="endGameForm"
action="{% url 'standings' gameid=game.id username=user.username%}"
method="get"
style="display: none"
>
{% csrf_token %}
</form>
<!-- Zeile für den oberen Inhalt -->
<div class="container-fluid g-0">
<div class="col-md-4 col-coloring overflow-y-auto">
<div class="row justify-content-evenly g-0">
<div class="col-md-6 p-3">
<!-- Inhalt links Zeile 1 -->
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 shadow rounded"
>
Workers
</h1>
{%for worker in company.workers.all%}
<a
class="viewlinker"
href="{% url 'companyWorker' gameid=game.id username=user.username workerid=worker.id %}"
>
<div
class="card border-primary mb-3 shadow-lg"
style="max-width: 540px"
>
<div class="row g-0">
<div class="col-md-4 align-self-center">
<img
src="{% static 'mygame/images/worker01.png' %}"
class="img-thumbnail"
alt="worker"
/>
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title justify-content-evenly">
{{worker.name}} {%if worker.sick == True%}
<p class="text-danger">[sick]</p>
{%elif worker.status == 2%}
<p class="text-success">[working]</p>
{%elif worker.status == 3%}
<p class="text-warning">[training]</p>
{%endif%}
</h5>
<div
class="progress mb-2"
role="progressbar"
aria-label="worker-happyness"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
{%if worker.happyness > 55 %}
<div
class="progress-bar overflow-visible text-dark bg-success"
style="width: {{worker.happyness}}%"
>
happyness
</div>
{% else%}
<div
class="progress-bar overflow-visible text-dark bg-danger"
style="width: {{worker.happyness}}%"
>
happyness
</div>
{%endif%}
</div>
<div class="row">
<div class="col-md-6">
<div
class="progress"
role="progressbar"
aria-label="worker-experience"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.experience}}%"
>
experience
</div>
</div>
<div
class="progress"
role="progressbar"
aria-label="worker-reliability"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.reliability}}%"
>
reliability
</div>
</div>
<div
class="progress"
role="progressbar"
aria-label="worker-python"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.python}}%"
>
python
</div>
</div>
</div>
<div class="col-md-6">
<div
class="progress"
role="progressbar"
aria-label="worker-javascript"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.javascript}}%"
>
javascript
</div>
</div>
<div
class="progress"
role="progressbar"
aria-label="worker-cpp"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.cpp}}%"
>
cpp
</div>
</div>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.management}}%"
>
management
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</a>
{%endfor%}
</div>
<div class="col-md-6 p-3">
<!-- Inhalt links Zeile 2 -->
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 shadow rounded"
>
Orders
</h1>
{%for order in company.orders.all%}
<a
class="viewlinker"
href="{% url 'companyOrder' gameid=game.id username=user.username orderid=order.id %}"
>
<!-- Quelle Bild https://pixabay.com/de/vectors/ausr%C3%BCstung-symbol-service-aufbau-1674891/-->
<div
class="card border-primary mb-3 shadow-lg"
style="
max-width: 540px;
background-image: url('{%static 'mygame/images/order.png'%}');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
"
>
<div class="row g-0">
<div class="col-md-12">
<div class="card-body">
<h5
class="card-title border-bottom font-weight-bold fs-4"
>
{{order.name}}
</h5>
<div class="card-text fs-5">
<p>Model: {{order.engineeringModel}}</p>
<p>Profit: {{order.profit}}</p>
<p>Rounds left: {{order.maxRounds}}</p>
</div>
</div>
</div>
</div>
</div>
</a>
{%endfor%}
</div>
</div>
</div>
<div class="col-md-4 overflow-y-auto g-0">
<!-- Inhalt mittlerer Block -->
<div>{% block content %}{% endblock %}</div>
</div>
<div class="col-md-4 col-coloring overflow-y-auto">
<div class="row g-0">
<div class="col-md-6 p-3">
<!-- Inhalt rechts Zeile 1 -->
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 shadow rounded fs-2"
>
Workermarket
</h1>
{%for worker in company.workermarket.all%}
<a
class="viewlinker"
href="{% url 'companyWorker' gameid=game.id username=user.username workerid=worker.id %}"
>
<div
class="card border-primary mb-3 shadow-lg"
style="max-width: 540px"
>
<div class="row g-0">
<div class="col-md-4 align-self-center">
<img
src="{% static 'mygame/images/worker01.png' %}"
class="img-thumbnail"
alt="worker"
/>
</div>
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">{{worker.name}}</h5>
<div class="row"><p>{{worker.skilledModels}}</p></div>
<div class="row">
<div class="col-md-6">
<div
class="progress"
role="progressbar"
aria-label="worker-experience"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.experience}}%"
>
experience
</div>
</div>
<div
class="progress"
role="progressbar"
aria-label="worker-reliability"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.reliability}}%"
>
reliability
</div>
</div>
<div
class="progress"
role="progressbar"
aria-label="worker-python"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.python}}%"
>
python
</div>
</div>
</div>
<div class="col-md-6">
<div
class="progress"
role="progressbar"
aria-label="worker-javascript"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.javascript}}%"
>
javascript
</div>
</div>
<div
class="progress"
role="progressbar"
aria-label="worker-cpp"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.cpp}}%"
>
cpp
</div>
</div>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{worker.attributes.management}}%"
>
management
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</a>
{%endfor%}
</div>
<div class="col-md-6 p-3">
<!-- Inhalt rechts Zeile 2 -->
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 shadow rounded fs-2"
>
Ordermarket
</h1>
{%for order in game.ordermarket.all%}
<a
class="viewlinker"
href="{% url 'companyOrder' gameid=game.id username=user.username orderid=order.id %}"
>
<!-- Quelle Bild https://pixabay.com/de/vectors/ausr%C3%BCstung-symbol-service-aufbau-1674891/-->
<div
class="card border-primary mb-3 shadow-lg"
style="
max-width: 540px;
background-image: url('{%static 'mygame/images/order.png'%}');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
"
>
<div class="row g-0">
<div class="col-md-12">
<div class="card-body">
<h5
class="card-title border-bottom font-weight-bold fs-4"
>
{{order.name}}
</h5>
<div class="card-text fs-5">
<p>estimated profit: {{order.profit}}</p>
<p>max. rounds: {{order.maxRounds}}</p>
</div>
</div>
</div>
</div>
</div>
</a>
{%endfor%}
</div>
</div>
</div>
</div>
<!-- Zeile für den unteren Inhalt -->
<div class="bottom-row text-center">
<h1>Actions</h1>
<div class="row g-0">
{%for action in company.actions.all%}
<div class="col-md-3">
<a
class="viewlinker"
href="{% url 'companyAction' gameid=game.id username=user.username actionid=action.id%}"
>
<div class="text-light border border-white p-1 m-1 rounded">
{{action.name}}
</div>
</a>
</div>
{%endfor%}
</div>
</div>
<!-- Bootstrap einbinden -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.min.js"></script>
</body>
</html>
+102
View File
@@ -0,0 +1,102 @@
{% extends "mygame/company.html" %} {% block content %} {% load filters %}
<div>
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded"
>
E-Mails
</h1>
<form
class="row g-0 justify-content-evenly m-2"
action="{% url 'companyEvent' gameid=game.id username=user.username eventnumber=eventnumber%}"
method="post"
>
{% csrf_token %}
<div class="col-md-6">
<div class="d-grid gap-2">
<input
class="btn btn-primary btn-block m-2"
type="submit"
value="previous"
id="previous"
name="action"
/>
</div>
</div>
<div class="col-md-6">
<div class="d-grid gap-2">
<input
class="btn btn-primary btn-block m-2"
type="submit"
value="next"
id="next"
name="action"
/>
</div>
</div>
</form>
<div
class="row g-0 justify-content-center border border-secondary-subtle rounded m-3"
>
<div class="col-md-10">
<h2
class="border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
{{companyevent.name}}
</h2>
</div>
<div class="col-md-9 m-4">{{companyevent.description}}</div>
{%if companyevent.modelset == False%}
<form
class="col-md-8"
action="{% url 'companyEventSetModel' gameid=game.id username=user.username eventid=companyevent.id modelnumber=0%}"
method="post"
>
{% csrf_token %}
<div class="d-grid gap-2">
<input
class="btn btn-warning btn-block m-2"
type="submit"
value="choose model"
id="choose model"
name="action"
/>
</div>
</form>
{%endif%} {% if companyevent|isInstanceOf:"SpecialOrder" %}
<form
class="row g-0 justify-content-evenly m-2"
action="{% url 'companySpecialOrder' gameid=game.id username=user.username specialorderid=companyevent.id%}"
method="post"
>
{% csrf_token %}
<div class="row justify-content-center">
<div class="col-md-4">
<div class="d-grid gap-2">
<input
class="btn btn-success btn-block m-2"
type="submit"
value="handle"
id="handle"
name="action"
/>
</div>
</div>
<div class="col-md-4">
<div class="d-grid gap-2">
<input
class="btn btn-danger btn-block m-2"
type="submit"
value="ignore"
id="ignore"
name="action"
/>
</div>
</div>
</div>
</form>
{%endif%}
</div>
</div>
{% endblock %}
@@ -0,0 +1,103 @@
{% extends "mygame/company.html" %} {% block content %}
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded"
>
Model: {{engineeringmodel.name}}
</h1>
<form
class="row g-0 justify-content-evenly m-2"
action="{% url 'companyEventSetModel' gameid=game.id username=user.username eventid=eventid modelnumber=modelnumber%}"
method="post"
>
{% csrf_token %}
<div class="col-md-6">
<div class="d-grid gap-2">
<input
class="btn btn-primary btn-block m-2"
type="submit"
value="previous"
id="previous"
name="action"
/>
</div>
</div>
<div class="col-md-6">
<div class="d-grid gap-2">
<input
class="btn btn-primary btn-block m-2"
type="submit"
value="next"
id="next"
name="action"
/>
</div>
</div>
</form>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Description
</h2>
<div class="row g-0 justify-content-center m-2 mt-4 mb-4">
<div class="d-grid gap-2">
<button
class="btn btn-info"
type="button"
data-bs-toggle="collapse"
data-bs-target="#collapseDescription"
aria-expanded="false"
aria-controls="collapseDescription"
>
View Description
</button>
</div>
<div class="collapse col-md-9 m-2" id="collapseDescription">
<div class="card card-body">{{engineeringmodel.description}}</div>
</div>
</div>
<div class="m-2">
<table class="table">
<thead>
<tr class="justify-content-center">
<th scope="col" class="text-success text-center fs-2">Positives</th>
<th scope="col" class="text-danger text-center fs-2">Negatives</th>
</tr>
</thead>
<tbody>
<tr>
<td>
{%for pro in engineeringmodel.getPros%}
<div class="border border-success-subtle rounded p-2 m-2">
{{pro}}
</div>
{%endfor%}
</td>
<td>
{%for con in engineeringmodel.getCons%}
<div class="border border-danger-subtle rounded p-2 m-2">{{con}}</div>
{%endfor%}
</td>
</tr>
</tbody>
</table>
</div>
<form
class="row g-0 justify-content-evenly m-2"
action="{% url 'companyEventSetModel' gameid=game.id username=user.username eventid=eventid modelnumber=modelnumber%}"
method="post"
>
{% csrf_token %}
<div class="d-grid gap-2">
<input
class="btn btn-warning"
type="submit"
value="set model"
id="set model"
name="action"
/>
</div>
</form>
{% endblock %}
File diff suppressed because it is too large Load Diff
+170
View File
@@ -0,0 +1,170 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Lobby</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css"
/>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
background-color: lightgray;
}
/* Stil für den Kopfbereich */
.header {
background-color: #333;
color: white;
padding: 10px;
text-align: center;
}
/* Stil für die Buttons im Kopfbereich */
.header button {
margin: 10px;
}
.container-fluid {
background-color: lightgray;
}
</style>
</head>
<body>
<!-- Kopfzeile mit Buttons -->
<div class="header">
<div class="row g-0 align-items-center">
<div class="col-md-6">
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 shadow rounded"
>
Gamelobby for {{game.name}}
</h1>
</div>
<div class="col-md-6">
{%if game.gamemaster == user.username%}
<form
class="m-2"
action="{% url 'startGame' gameid=game.id username=user.username%}"
method="post"
>
{% csrf_token %}
<input
class="btn btn-success col-md-12"
type="submit"
value="start game"
id="startGame"
name="action"
/>
</form>
{%else%}
<form
class="m-2"
action="{% url 'gamerules' gameid=game.id%}"
method="get"
>
{% csrf_token %}
<input
class="btn btn-primary col-md-12"
type="submit"
value="view gamerules"
id="viewgamerules"
name="action"
/>
</form>
{%endif%}
</div>
</div>
</div>
<div class="container-fluid overflow-y-auto">
<div class="row">
<div class="col">
<h1
class="col-md-6 bg-secondary-subtle text-center font-weight-bold border-bottom border-2 border-primary p-3 mt-3 shadow rounded"
>
Game ID: {{game.id}}
</h1>
<h1
class="col-md-6 bg-secondary-subtle text-center font-weight-bold border-bottom border-2 border-primary p-3 mt-3 shadow rounded"
>
Gamemaster: {{game.gamemaster}}
</h1>
<ul class="list-group mb-3">
<li class="list-group-item bg-secondary-subtle">
<h1
class="text-center bg-secondary-subtle font-weight-bold border-bottom border-2 border-primary p-3 mt-3 shadow rounded"
>
Joined Players:
</h1>
</li>
{%for player in game.participants.all%}
<li class="list-group-item bg-secondary-subtle fs-4">
{{player.name}}
</li>
{% endfor %}
</ul>
</div>
<div class="col">
<h1
class="text-center bg-secondary-subtle font-weight-bold border-bottom border-2 border-primary p-3 mt-3 shadow rounded"
>
Gamesettings:
</h1>
{%if game.gamemaster == user.username%}
<form
action="{% url 'lobby' gameid=game.id username=user.username%}"
method="post"
>
{% csrf_token %}
<ul class="list-group">
<li class="list-group-item bg-secondary-subtle">
Number of rounds: {{ gamesettingsform.rounds }}
</li>
<li class="list-group-item bg-secondary-subtle">
Roundtimer: {{ gamesettingsform.timer }}
</li>
<li class="list-group-item bg-secondary-subtle">
Ordermarket size: {{ gamesettingsform.ordermarketsize }}
</li>
</ul>
<div class="d-grid gap-2 mt-2">
<button
class="btn btn-primary"
type="submit"
value="changesettings"
id="changesettings"
name="action"
>
save settings
</button>
</div>
</form>
{%else%}
<ul class="list-group">
<li class="list-group-item bg-secondary-subtle">
Number of rounds: {{gamesettingsform.rounds.initial}}
</li>
<li class="list-group-item bg-secondary-subtle">
Roundtimer: {{gamesettingsform.timer.initial}}
</li>
<li class="list-group-item bg-secondary-subtle">
Ordermarket size: {{gamesettingsform.ordermarketsize.initial}}
</li>
</ul>
</div>
{%endif%}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.min.js"></script>
</body>
</html>
+53
View File
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Login</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css"
/>
<style>
body {
background-color: grey;
}
.container {
padding: 20px;
background-color: lightblue;
border: 2px solid black;
text-align: center;
}
.errormessage {
color: red;
}
</style>
</head>
<body class="body">
<div class="container">
{%if error_message%}
<div class="errormessage">{{error_message}}</div>
{% endif %}
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded"
>
Login
</h1>
<form
class="row g-0 justify-content-center"
action="{% url 'loginView' %}"
method="post"
>
{% csrf_token %} {%for field in form%}
<div class="col-md-12 fs-3">{{field.label}}</div>
<div class="col-md-12 m-2">{{field}}</div>
{%endfor%}
<div class="col-md-6 m-2">
<button type="submit" class="col-md-12 btn btn-primary">
Start!
</button>
</div>
</form>
</div>
</body>
</html>
+247
View File
@@ -0,0 +1,247 @@
{% extends "mygame/company.html" %} {% block content %}
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded"
>
Order: {{viewedorder.name}}
</h1>
{%if errormessage%}
<div class="m-2 pb-0 text-center text-light bg-danger rounded">
{{errormessage}}
</div>
{%endif%}
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Workload
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Required Skill</th>
<th scope="col">Workload</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">experience</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-experience"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedorder.requiredWorkload.experience}}%"
>
{{viewedorder.requiredWorkload.experience}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">reliability</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-reliability"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedorder.requiredWorkload.reliability}}%"
>
{{viewedorder.requiredWorkload.reliability}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">python</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-python"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedorder.requiredWorkload.python}}%"
>
{{viewedorder.requiredWorkload.python}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">javascript</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-javascript"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedorder.requiredWorkload.javascript}}%"
>
{{viewedorder.requiredWorkload.javascript}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">cpp</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-cpp"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedorder.requiredWorkload.cpp}}%"
>
{{viewedorder.requiredWorkload.cpp}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">management</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedorder.requiredWorkload.management}}%"
>
{{viewedorder.requiredWorkload.management}}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Attributes
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Attribute</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
{%if viewedorder.status == 0%}
<th scope="row">Estimated Profit</th>
{%else%}
<th scope="row">Profit</th>
{% endif%}
<td>{{viewedorder.profit}}</td>
</tr>
<tr>
{%if viewedorder.status == 0%}
<th scope="row">Maximum Rounds</th>
{%else%}
<th scope="row">Rounds left</th>
{% endif%}
<td>{{viewedorder.maxRounds}}</td>
</tr>
{%if viewedorder.status == 1%}
<tr>
<th scope="row">Engineeringmodel</th>
<td>{{viewedorder.engineeringModel}}</td>
</tr>
{% endif%}
<tr>
<th scope="row">Customer Description</th>
<td>{{viewedorder.specialorder.hint}}</td>
</tr>
</tbody>
</table>
</div>
<form
class="row g-0 justify-content-evenly m-2"
action="{% url 'companyOrder' gameid=game.id username=user.username orderid=viewedorder.id %}"
method="post"
>
{% csrf_token %} {%if viewedorder.status == 0 %}
<div class="row g-0 justify-content-evenly">
<div class="col-md-6 p-2">
<input
class="form-control"
type="number"
placeholder="Insert your Offer"
id="offerfield"
name="offerfield"
/>
</div>
<div class="col-md-6 p-2">
<input
class="btn btn-primary w-100"
type="submit"
value="offer"
id="offer"
name="action"
/>
</div>
</div>
{%elif viewedorder.status == 1 %}
<div class="col-md-6">
<div class="d-grid gap-2">
<input
class="btn btn-danger btn-block m-2"
type="submit"
value="cancel"
id="cancel"
name="action"
/>
</div>
</div>
<div class="col-md-6">
<div class="d-grid gap-2">
<input
class="btn btn-success btn-block m-2"
type="submit"
value="assign resources"
id="assign resources"
name="action"
/>
</div>
</div>
{%endif%}
</form>
{% endblock %}
+57
View File
@@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Standings</title>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css"
/>
<style>
body {
margin: 0;
padding: 0;
background-color: #e6f2ff;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded"
>
Leaderboard for {{game.name}}
</h1>
<table class="table table-striped p-3 m-3 shadow rounded">
<thead>
<tr>
<th scope="col">Place</th>
<th scope="col">Company</th>
<th scope="col">Money</th>
</tr>
</thead>
<tbody>
{%for item in leaderboard%}
<div>
<tr>
<td>{{item.0}}</td>
<td>{{item.1.name}}</td>
<td>{{item.1.money}}$</td>
</tr>
</div>
{%endfor%}
</tbody>
</table>
<div>Please complete the following Survey:</div>
<a href="https://www.survio.com/survey/d/V6G8P1V8W7N1Z6E3Y">Survey</a>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.min.js"></script>
</body>
</html>
+248
View File
@@ -0,0 +1,248 @@
{% extends "mygame/company.html" %} {% block content %}
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded"
>
Training: {{trainworker.name}}
</h1>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Description
</h2>
<div class="row g-0 justify-content-center m-2">
<div class="col-md-12 m-2 p-2 border border-secondary-subtle rounded">
<p>Choose a skill that you want to train (add 10 points).</p>
<p class="text-danger">
The worker will be blocked from working on orders for one round!
</p>
</div>
<form
action="{% url 'companyTraining' gameid=game.id username=user.username workerid=trainworker.id %}"
method="post"
>
{% csrf_token %}
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Skill</th>
<th scope="col">Strength</th>
<th scope="col">Selection</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">experience</th>
<td>
<div
class="progress align-self-center"
role="progressbar"
aria-label="worker-experience"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{trainworker.attributes.experience}}%"
>
{{trainworker.attributes.experience}}
</div>
</div>
</td>
<td>
<input
type="radio"
class="btn-check"
name="trainskill"
id="experienceRadio"
value="experience"
autocomplete="off"
/>
<label class="btn btn-outline-primary" for="experienceRadio"
>train</label
>
</td>
</tr>
<tr>
<th scope="row">reliability</th>
<td>
<div
class="progress align-self-center"
role="progressbar"
aria-label="worker-reliability"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{trainworker.attributes.reliability}}%"
>
{{trainworker.attributes.reliability}}
</div>
</div>
</td>
<td>
<input
type="radio"
class="btn-check"
name="trainskill"
id="reliabilityRadio"
value="reliability"
autocomplete="off"
/>
<label class="btn btn-outline-primary" for="reliabilityRadio"
>train</label
>
</td>
</tr>
<tr>
<th scope="row">python</th>
<td>
<div
class="progress align-self-center"
role="progressbar"
aria-label="worker-python"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{trainworker.attributes.python}}%"
>
{{trainworker.attributes.python}}
</div>
</div>
</td>
<td>
<input
type="radio"
class="btn-check"
name="trainskill"
id="pythonRadio"
value="python"
autocomplete="off"
/>
<label class="btn btn-outline-primary" for="pythonRadio"
>train</label
>
</td>
</tr>
<tr>
<th scope="row">javascript</th>
<td>
<div
class="progress align-self-center"
role="progressbar"
aria-label="worker-javascript"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{trainworker.attributes.javascript}}%"
>
{{trainworker.attributes.javascript}}
</div>
</div>
</td>
<td>
<input
type="radio"
class="btn-check"
name="trainskill"
id="javascriptRadio"
value="javascript"
autocomplete="off"
/>
<label class="btn btn-outline-primary" for="javascriptRadio"
>train</label
>
</td>
</tr>
<tr>
<th scope="row">cpp</th>
<td>
<div
class="progress align-self-center"
role="progressbar"
aria-label="worker-cpp"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{trainworker.attributes.cpp}}%"
>
{{trainworker.attributes.cpp}}
</div>
</div>
</td>
<td>
<input
type="radio"
class="btn-check"
name="trainskill"
id="cppRadio"
value="cpp"
autocomplete="off"
/>
<label class="btn btn-outline-primary" for="cppRadio"
>train</label
>
</td>
</tr>
<tr>
<th scope="row">management</th>
<td>
<div
class="progress align-self-center"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{trainworker.attributes.management}}%"
>
{{trainworker.attributes.management}}
</div>
</div>
</td>
<td>
<input
type="radio"
class="btn-check"
name="trainskill"
id="managementRadio"
value="management"
autocomplete="off"
/>
<label class="btn btn-outline-primary" for="managementRadio"
>train</label
>
</td>
</tr>
</tbody>
</table>
</div>
<div class="d-grid gap-2">
<input
class="btn btn-success"
type="submit"
value="start training"
id="start training"
name="action"
/>
</div>
</form>
</div>
{% endblock %}
+243
View File
@@ -0,0 +1,243 @@
{% extends "mygame/company.html" %} {% block content %}
<h1
class="text-center font-weight-bold border-bottom border-2 border-primary p-3 m-3 shadow rounded"
>
Worker: {{viewedworker.name}}
</h1>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Skills
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Skill</th>
<th scope="col">Strength</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">experience</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-experience"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedworker.attributes.experience}}%"
>
{{viewedworker.attributes.experience}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">reliability</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-reliability"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedworker.attributes.reliability}}%"
>
{{viewedworker.attributes.reliability}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">python</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-python"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedworker.attributes.python}}%"
>
{{viewedworker.attributes.python}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">javascript</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-javascript"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedworker.attributes.javascript}}%"
>
{{viewedworker.attributes.javascript}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">cpp</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-cpp"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedworker.attributes.cpp}}%"
>
{{viewedworker.attributes.cpp}}
</div>
</div>
</td>
</tr>
<tr>
<th scope="row">management</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedworker.attributes.management}}%"
>
{{viewedworker.attributes.management}}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<h2
class="col-md-4 border-bottom border-1 border-primary p-2 m-2 mt-4 shadow rounded text-center"
>
Attributes
</h2>
<div class="m-2">
<table class="table">
<thead>
<tr>
<th scope="col">Attribute</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Skilled Model</th>
<td>{{viewedworker.skilledModels}}</td>
</tr>
<tr>
<th scope="row">Amplifyer</th>
<td>{{viewedworker.amplifyer}}</td>
</tr>
<tr>
<th scope="row">Salary</th>
<td>{{viewedworker.salary}}</td>
</tr>
<tr>
<th scope="row">Happyness</th>
<td>
<div
class="progress"
role="progressbar"
aria-label="worker-management"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
>
<div
class="progress-bar overflow-visible text-dark"
style="width: {{viewedworker.happyness}}%"
>
{{viewedworker.happyness}}
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<form
action="{% url 'companyWorker' gameid=game.id username=user.username workerid=viewedworker.id %}"
method="post"
>
<div class="d-grid gap-2">
{% csrf_token %} {%if viewedworker.status == 0 %}
<input
class="btn btn-primary m-2"
type="submit"
value="hire"
id="hire"
name="action"
/>
{%elif viewedworker.status == 2 or viewedworker.status == 3 %}
<input
class="btn btn-danger m-2"
type="submit"
value="fire"
id="fire"
name="action"
disabled="True"
/>
<input
class="btn btn-primary m-2 mt-0"
type="submit"
value="train"
id="train"
name="action"
disabled="True"
/>
{%else%}
<input
class="btn btn-danger m-2"
type="submit"
value="fire"
id="fire"
name="action"
/>
<input
class="btn btn-primary m-2 mt-0"
type="submit"
value="train"
id="train"
name="action"
/>
{%endif%}
</div>
</form>
{% endblock %}
View File
+11
View File
@@ -0,0 +1,11 @@
from django import template
from mygame.backend.event import SpecialOrder
register = template.Library()
#so kann man isinstance im frontend nutzen
# (KLASSEN DIE MAN FILTERN WILL IMPORTIEREN)
@register.filter
def isInstanceOf(value, classname):
classobject = eval(classname)
return isinstance(value, classobject)
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+51
View File
@@ -0,0 +1,51 @@
from django.urls import path
from . import views
urlpatterns = [
path("", views.loginView, name="loginView"),
path("lobby/<int:gameid>/<str:username>", views.lobby, name="lobby"),
path("gamerules/<int:gameid>/", views.gamerules, name="gamerules"),
path(
"company/<int:gameid>/<str:username>/startGame/",
views.startGame,
name="startGame",
),
path(
"company/<int:gameid>/<str:username>/worker/<int:workerid>/",
views.companyWorker,
name="companyWorker",
),
path(
"company/<int:gameid>/<str:username>/order/<int:orderid>/",
views.companyOrder,
name="companyOrder",
),
path(
"company/<int:gameid>/<str:username>/training/<int:workerid>/",
views.companyTraining,
name="companyTraining",
),
path(
"company/<int:gameid>/<str:username>/action/<int:actionid>/",
views.companyAction,
name="companyAction",
),
path(
"company/<int:gameid>/<str:username>/events/<int:eventnumber>/",
views.companyEvent,
name="companyEvent",
),
path(
"company/<int:gameid>/<str:username>/setModel/<int:eventid>/<int:modelnumber>",
views.companyEventSetModel,
name="companyEventSetModel",
),
path(
"company/<int:gameid>/<str:username>/specialorder/<int:specialorderid>/",
views.companySpecialOrder,
name="companySpecialOrder",
),
path("company/<int:gameid>/<str:username>/", views.company, name="company"),
path("standings/<int:gameid>/<str:username>/", views.standings, name="standings"),
]
+479
View File
@@ -0,0 +1,479 @@
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.urls import reverse
from mygame.forms import *
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login
from django.shortcuts import redirect
import time
from mygame.backend.engineeringmodel import EngineeringModel
from .backend.game import Game
from .backend.timer import Timer
from .backend.company import Company
from .backend.worker import Worker
from .backend.order import Order
from .backend.action import Action
from .backend.game import Game
from .backend.engineeringmodel import EngineeringModel
from .backend.event import Event, SpecialOrder
def loginView(request):
if request.method == "POST":
try:
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
gameid = form.cleaned_data["game_id"]
password = form.cleaned_data["password"]
choice = form.cleaned_data["create_join_game"]
# Create oder Join angewählt?
if choice == "1":
lobby = Game.objects.get(id=int(gameid))
else:
timer = Timer.objects.create()
lobby, created = Game.objects.get_or_create(
name=username + "'s Game", gamemaster=username
)
lobby.timer = timer
lobby.save()
gameid = lobby.id
# Checken ob username existiert:
# Wenn Ja und passwort stimmt -> einloggen
# Wenn Ja und passwort flasch -> Fehler
# Wenn nein -> username mit passwort erstellen
if User.objects.filter(username=username).exists():
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
else:
raise NameError("Username already exists!")
else:
user = User.objects.create_user(
username=username, password=password
)
login(request, user)
company, created = Company.objects.get_or_create(
name=username, user=username
)
lobby.participants.add(company)
lobby.save()
except:
error_message = "FEHLER AUFGETRETEN"
else:
return HttpResponseRedirect(
reverse(
"lobby",
args=(
gameid,
username,
),
)
)
return render(
request,
"mygame/login.html",
{
"error_message": error_message,
"form": form,
},
)
else:
form = LoginForm()
return render(request, "mygame/login.html", {"form": form})
def lobby(request, gameid, username):
game = get_object_or_404(Game, id=gameid)
if request.method == "POST":
if request.POST.get("action", False) == "clearlobby":
game.clearParticipants(username)
if request.POST.get("action", False) == "changesettings":
gamesettingsform = GamesettingsForm(
request.POST,
initial={
"timer": game.timer.timer,
"rounds": game.maxRounds,
"ordermarketsize": game.ordermarketsize,
},
)
try:
if gamesettingsform.is_valid():
game.maxRounds = gamesettingsform.cleaned_data["rounds"]
game.ordermarketsize = gamesettingsform.cleaned_data[
"ordermarketsize"
]
game.timer.timer = gamesettingsform.cleaned_data["timer"]
game.timer.remainingtimer = gamesettingsform.cleaned_data["timer"]
game.save()
game.timer.save()
except (KeyError, game.DoesNotExist):
return render(
request,
"mygame/lobby.html",
{
"lobby": game,
"gamesettingsform": gamesettingsform,
"error_message": "EIN FEHLER IST AUFGETRETEN.",
},
)
# hier errormessages je nach fehler ausgeben
else:
return HttpResponseRedirect(
reverse(
"lobby",
args=(
gameid,
username,
),
)
)
gamesettingsform = GamesettingsForm(
initial={
"timer": game.timer.timer,
"rounds": game.maxRounds,
"ordermarketsize": game.ordermarketsize,
}
)
return render(
request,
"mygame/lobby.html",
{"game": game, "gamesettingsform": gamesettingsform},
)
def gamerules(request, gameid):
game = get_object_or_404(Game, id=gameid)
return render(
request,
"mygame/gamerules.html",
{
"game": game,
},
)
def startGame(request, gameid, username):
game = get_object_or_404(Game, id=gameid)
game.startGame()
return redirect("company", gameid=gameid, username=username)
def company(request, gameid, username):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
if request.method == "POST":
if request.POST["action"] == "next round":
gameend = game.processGameround()
if gameend:
return redirect("standings", gameid=gameid, username=username)
else:
eventtuple = company.getEvent(0, "default")
companyevent = eventtuple[0]
eventnumber = eventtuple[1]
return render(
request,
"mygame/email.html",
{
"game": game,
"company": company,
"companyevent": companyevent,
"eventnumber": eventnumber,
},
)
return render(request, "mygame/company.html", {"game": game, "company": company})
def companyWorker(request, gameid, username, workerid):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
try:
viewedworker = Worker.objects.get(id=workerid)
except:
return render(
request,
"mygame/company.html",
{"game": game, "company": company},
)
if request.method == "POST":
if request.POST["action"] == "hire":
viewedaction = company.actionEmploy(viewedworker)
return render(
request,
"mygame/action.html",
{"game": game, "company": company, "viewedaction": viewedaction},
)
elif request.POST["action"] == "fire":
viewedaction = company.actionUnemploy(viewedworker)
return render(
request,
"mygame/action.html",
{"game": game, "company": company, "viewedaction": viewedaction},
)
elif request.POST["action"] == "train":
return companyTraining(request, gameid, username, workerid)
return render(
request,
"mygame/worker.html",
{"game": game, "company": company, "viewedworker": viewedworker},
)
def companyOrder(request, gameid, username, orderid):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
try:
viewedorder = get_object_or_404(Order, id=orderid)
except:
return render(
request,
"mygame/company.html",
{"game": game, "company": company},
)
if request.method == "POST":
if request.POST["action"] == "offer":
try:
amount = int(request.POST["offerfield"])
acceptoffer = viewedorder.checkOffer(amount)
if acceptoffer == False:
errormessage = "you can only offer 20 percent higher or lower than the estimated profit"
return render(
request,
"mygame/order.html",
{
"game": game,
"company": company,
"viewedorder": viewedorder,
"errormessage": errormessage,
},
)
except:
errormessage = "please enter numbers only"
return render(
request,
"mygame/order.html",
{
"game": game,
"company": company,
"viewedorder": viewedorder,
"errormessage": errormessage,
},
)
else:
viewedaction = company.actionOffer(order=viewedorder, amount=amount)
return render(
request,
"mygame/action.html",
{"game": game, "company": company, "viewedaction": viewedaction},
)
if request.POST["action"] == "assign resources":
return render(
request,
"mygame/assign.html",
{"game": game, "company": company, "assignorder": viewedorder},
)
if request.POST["action"] == "cancel":
viewedaction = company.actionCancelOrder(viewedorder)
return render(
request,
"mygame/action.html",
{"game": game, "company": company, "viewedaction": viewedaction},
)
if request.POST["action"] == "save assignment":
for worker in company.workers.all():
workerid = request.POST.get("assign " + str(worker.id), 0)
if workerid != 0:
viewedorder.assignWorker(worker)
viewedorder.save()
workerid = request.POST.get("unassign " + str(worker.id), 0)
if workerid != 0:
viewedorder.unassignWorker(worker)
viewedorder.save()
return render(
request,
"mygame/assign.html",
{"game": game, "company": company, "assignorder": viewedorder},
)
return render(
request,
"mygame/order.html",
{"game": game, "company": company, "viewedorder": viewedorder},
)
def companyTraining(request, gameid, username, workerid):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
try:
trainworker = get_object_or_404(Worker, id=workerid)
except:
return render(
request,
"mygame/company.html",
{"game": game, "company": company},
)
if request.method == "POST":
trainskill = request.POST.get("trainskill", False)
if trainskill:
viewedaction = company.actionTrain(
worker=trainworker, trainskill=trainskill
)
return render(
request,
"mygame/action.html",
{"game": game, "company": company, "viewedaction": viewedaction},
)
return render(
request,
"mygame/training.html",
{"game": game, "company": company, "trainworker": trainworker},
)
def companyAction(request, gameid, username, actionid):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
# hier schauen welche action es ist dann aus entsprechender table holen
try:
viewedaction = get_object_or_404(Action, id=actionid)
except:
return render(
request,
"mygame/company.html",
{"game": game, "company": company},
)
if request.method == "POST":
if request.POST["action"] == "cancel":
company.cancelAction(id=actionid)
return render(
request,
"mygame/company.html",
{"game": game, "company": company},
)
return render(
request,
"mygame/action.html",
{"game": game, "company": company, "viewedaction": viewedaction},
)
def companyEvent(request, gameid, username, eventnumber):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
if request.method == "POST":
if request.POST.get("action", False) == "previous":
eventresult = company.getEvent(eventnumber, "previous")
if request.POST.get("action", False) == "next":
eventresult = company.getEvent(eventnumber, "next")
else:
eventresult = company.getEvent(eventnumber, "default")
companyevent = eventresult[0]
eventnumber = eventresult[1]
return render(
request,
"mygame/email.html",
{
"game": game,
"company": company,
"companyevent": companyevent,
"eventnumber": eventnumber,
},
)
def companyEventSetModel(request, gameid, username, eventid, modelnumber):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
engineeringmodels = EngineeringModel.objects.all()
if request.method == "POST":
if request.POST.get("action", False) == "previous":
modelnumber -= 1
if modelnumber < 0:
modelnumber = engineeringmodels.count() - 1
engineeringmodel = engineeringmodels[modelnumber]
if request.POST.get("action", False) == "next":
modelnumber += 1
if modelnumber > (engineeringmodels.count() - 1):
modelnumber = 0
if request.POST.get("action", False) == "set model":
eventofferaccepted = Event.objects.get(id=eventid)
setmodel = engineeringmodels.order_by("id")[modelnumber]
eventofferaccepted.setModel(setmodel)
return render(
request,
"mygame/email.html",
{
"game": game,
"company": company,
"companyevent": eventofferaccepted,
"eventnumber": 0,
},
)
engineeringmodel = engineeringmodels.order_by("id")[modelnumber]
return render(
request,
"mygame/engineeringmodel.html",
{
"game": game,
"company": company,
"engineeringmodel": engineeringmodel,
"modelnumber": modelnumber,
"eventid": eventid,
},
)
def companySpecialOrder(request, gameid, username, specialorderid):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
if request.method == "POST":
specialorder = SpecialOrder.objects.get(id=specialorderid)
for order in company.orders.all():
if order.specialorder.id == specialorderid:
order = order
if request.POST.get("action", False) == "handle":
event = specialorder.handle(order=order, company=company, handle=True)
if request.POST.get("action", False) == "ignore":
event = specialorder.handle(order=order, company=company, handle=False)
return render(
request,
"mygame/email.html",
{"game": game, "company": company, "companyevent": event, "eventnumber": 0},
)
def standings(request, gameid, username):
game = get_object_or_404(Game, id=gameid)
company = get_object_or_404(Company, user=username)
leaderboard = game.createLeaderboard()
return render(
request,
"mygame/standings.html",
{"game": game, "company": company, "leaderboard": leaderboard},
)