from __future__ import annotations
from abc import ABC, abstractmethod
from enum import Enum
import re
'''
Failure types:
- ok: no fail
- requip: item should be added
- cloudian: algorithm goes to stand by in its Dclass
- fail: no input
'''
class enumFail(Enum):
fail = "fail"
requip = "requip"
dequip = "dequip"
cloudian = "cloudian"
ok = "ok"
class Mutatable(ABC):
@abstractmethod
def action(self, ear: str, skin: str, eye: str) -> str:
"""Returns action string"""
...
@abstractmethod
def failure(self, input: str) -> enumFail:
"""Failure type only mutatable may use enumFail.fail"""
pass
@abstractmethod
def completed(self) -> bool:
"""Has finished ?"""
pass
@abstractmethod
def clone(self) -> Mutatable:
pass
def getMutationLimit(self) -> int:
return 0
def myName(self) -> str:
"""Returns the class name"""
return self.__class__.__name__
def mutation(self) -> Mutatable:
self.clone()
'''!!! CHILD TEST CLASS TO REMOVE !!!'''
class T1(Mutatable):
def mutation(self) -> Mutatable:
print("t1 mutating into t2")
return T2()
def clone(self) -> Mutatable:
print("t1 cloning another t1")
return T1()
# Override
def action(self, ear: str, skin: str, eye: str) -> str:
"""Returns action string"""
...
# Override
def failure(self, input: str) -> enumFail:
"""Failure type only mutatable may use enumFail.fail"""
pass
# Override
def completed(self) -> bool:
"""Has finished ?"""
pass
# Override
def myName(self) -> str:
"""Returns the class name"""
return self.__class__.__name__
'''!!! CHILD TEST CLASS TO REMOVE !!!'''
class T2(Mutatable):
def mutation(self) -> Mutatable:
print("t2 mutating into t1")
return T1()
def clone(self) -> Mutatable:
print("t2 cloning another t2")
return T2()
# Override
def action(self, ear: str, skin: str, eye: str) -> str:
"""Returns action string"""
...
# Override
def failure(self, input: str) -> enumFail:
"""Failure type only mutatable may use enumFail.fail"""
pass
# Override
def completed(self) -> bool:
"""Has finished ?"""
pass
# Override
def myName(self) -> str:
"""Returns the class name"""
return self.__class__.__name__
class AbsDictionaryDB(ABC):
@abstractmethod
def save(self, key: str, value: str):
'''Returns action string'''
pass
@abstractmethod
def load(self, key: str) -> str:
'''TODO set to return null as default if key not found !!!'''
pass
class AbsDictionaryDBShadow(AbsDictionaryDB):
'''used as a fill in class if you want to test the chobit and havent built a DB class yet'''
# Override
def save(self, key: str, value: str):
pass
# Override
def load(self, key: str) -> str:
return "null"
class GrimoireMemento:
def __init__(self, absDictionaryDB: AbsDictionaryDB) -> None:
super().__init__()
self.rootToAPNumDic:dict[str, str] = {}
self.APNumToObjDic:dict[str, Mutatable] = {}
self.absDictionaryDB = absDictionaryDB
def load(self, obj: Mutatable) -> Mutatable:
'''load final mutation from memory of obj'''
objName = obj.__class__.__name__
objRoot = re.sub(r'\d+', '', objName)
# if not in active DB try adding from external DB
if not self.rootToAPNumDic.keys().__contains__(objRoot):
temp = self.absDictionaryDB.load(objRoot)
if temp != "null":
self.rootToAPNumDic[objRoot] = temp
if (not self.rootToAPNumDic.keys().__contains__(objRoot)):
self.rootToAPNumDic[objRoot] = objName
return obj
if (self.rootToAPNumDic[objRoot] == objName):
# the mutatable does not have mutations
return obj
else:
APNum = self.rootToAPNumDic[objRoot]
if (self.APNumToObjDic.keys().__contains__(APNum)):
return self.APNumToObjDic[APNum].clone()
else:
self.loadMutations(obj, objName, objRoot)
return self.APNumToObjDic[APNum].clone()
def reqquipMutation(self, mutationAPName: str):
'''save mutation'''
self.rootToAPNumDic[re.sub(r'\d+', '', mutationAPName)] = mutationAPName
self.absDictionaryDB.save(re.sub(r'\d+', '', mutationAPName), mutationAPName)
def loadMutations(self, obj: Mutatable, objName: str, objRoot: str):
'''
make sure all the AP mutation sets of obj are present
self assumes the last mutation mutates into the prime mutation
'''
mutant = obj
end = objName
while (True):
self.APNumToObjDic[obj.__class__.__name__] = obj.clone()
mutant = obj
obj = mutant.mutation()
if (end == obj.__class__.__name__):
break
def simpleLoad(self, key: str) -> str:
return self.absDictionaryDB.load(key)
def simpleSave(self, key: str, value: str):
if (key.startswith("AP") or key == "" or value == ""):
return
self.absDictionaryDB.save(key, value)
'''
all action data goes through here
* detects negatives such as : repetition, pain on various levels and failures
* serves as a database for memories, convos and alg generations
* can trigger revenge algs
* checks for % of difference in input for exploration type algs
'''
class Kokoro:
def __init__(self, absDictionaryDB: AbsDictionaryDB):
self.emot = ""
self.pain:dict[str, int] = {}
self.grimoireMemento = GrimoireMemento(absDictionaryDB)
self.toHeart:dict[str, str] = {}
self.fromHeart:dict[str, str] = {}
self.standBy = False
def getEmot(self) -> str:
return self.emot
def setEmot(self, emot: str):
self.emot = emot
def getPain(self, BijuuName: str) -> int:
try:
value = self.pain[BijuuName]
except:
value = 0
return value
def inside(self, chi: Chi):
pass
def outside(self, isCompleted: bool, failure: enumFail):
pass
class Chi(Mutatable):
'''
an adaptor pattern to the alg part, it also has the kokoro consiousness
object to be aware throughout the program of what is happening all action
data goes through this soul.
'''
def __init__(self, kokoro: Kokoro, ofSkill: str, aPart: Mutatable):
super().__init__()
self.kokoro = kokoro
self.ofSkill = ofSkill
self.aPart = kokoro.grimoireMemento.load(aPart)
def actualAction(self, ear: str, skin: str, eye: str) -> str:
return self.aPart.action(ear, skin, eye)
# Override
def action(self, ear: str, skin: str, eye: str) -> str:
self.kokoro.inside(self)
result = self.actualAction(ear, skin, eye)
self.kokoro.outside(self.completed(), self.failure(""))
return result
# Override
def failure(self, input: str) -> enumFail:
# TODO Auto-generated method stub
return self.aPart.failure(input)
# Override
def completed(self) -> bool:
# TODO Auto-generated method stub
return self.aPart.completed()
# Override
def clone(self) -> Mutatable:
# TODO Auto-generated method stub
return Chi(self.kokoro, self.ofSkill, self.aPart.clone())
# Override
def getMutationLimit(self) -> int:
# TODO Auto-generated method stub
return self.aPart.getMutationLimit()
# Override
def mutation(self) -> Mutatable:
mutant = self.aPart
tempAP = mutant.mutation()
self.kokoro.grimoireMemento.reqquipMutation(tempAP.__class__.__name__)
return Chi(self.kokoro, self.ofSkill, tempAP)
# Override
def myName(self) -> str:
return self.aPart.myName()
if __name__ == "__main__":
# Kokoro and Chi creation
mutatable = T1()
absDB = AbsDictionaryDBShadow()
kokoro = Kokoro(absDB)
chi = Chi(kokoro, "skill", mutatable)
# Kokoro test
print("\n---- KOKORO TESTING ----")
print("This should return nothing: " + kokoro.getEmot())
kokoro.setEmot("smiley")
print("This should return 'smiley': " + kokoro.getEmot())
print("This should return 0: " + str(kokoro.getPain("painful")))
# Chi test
print("\n---- CHI TESTING ----")
print("This should return None: " + str(chi.actualAction("ear", "skin", "eye")))
print("This should return None: " + str(chi.action("ear", "skin", "eye")))
print("This should return None: " + str(chi.failure("")))
print("This should return None: " + str(chi.completed()))
print("This should return 0: " + str(chi.getMutationLimit()))
print("This should return T1: " + chi.myName())
# Chi clone testing
print("\n---- CHI CLONE TESTING ----")
chiClone = chi.clone()
print("This should return None: " + str(chiClone.actualAction("ear", "skin", "eye")))
print("This should return None: " + str(chiClone.action("ear", "skin", "eye")))
print("This should return None: " + str(chiClone.failure("")))
print("This should return None: " + str(chiClone.completed()))
print("This should return 0: " + str(chiClone.getMutationLimit()))
print("This should return T1: " + chiClone.myName())
# Chi mutation testing
print("\n---- CHI MUTATION TESTING ----")
chiMuta = chi.mutation()
print("This should return 0: " + str(chiMuta.getMutationLimit()))
print("This should return T2: " + chiMuta.myName())
mutatable2 = T2() # dif result from t1 => works
chi = Chi(kokoro, "skill", mutatable2)