aboutsummaryrefslogtreecommitdiff
path: root/src/test/philo.py
diff options
context:
space:
mode:
authorCharles Cabergs <me@cacharle.xyz>2020-10-01 11:49:53 +0200
committerCharles Cabergs <me@cacharle.xyz>2020-10-01 11:49:53 +0200
commit1f18e740539aed751865ecff9d0f3cba44230e54 (patch)
treee23254751cc5a3be551233efb979a00571f40dc6 /src/test/philo.py
parent763f02a8b1e69c0e26a088824981d23ba1e5386d (diff)
downloadphilosophers_test-1f18e740539aed751865ecff9d0f3cba44230e54.tar.gz
philosophers_test-1f18e740539aed751865ecff9d0f3cba44230e54.tar.bz2
philosophers_test-1f18e740539aed751865ecff9d0f3cba44230e54.zip
Refactoring file structure, Added summary
Diffstat (limited to 'src/test/philo.py')
-rw-r--r--src/test/philo.py194
1 files changed, 0 insertions, 194 deletions
diff --git a/src/test/philo.py b/src/test/philo.py
deleted file mode 100644
index 3b49057..0000000
--- a/src/test/philo.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# ############################################################################ #
-# #
-# ::: :::::::: #
-# philo.py :+: :+: :+: #
-# +:+ +:+ +:+ #
-# By: charles <me@cacharle.xyz> +#+ +:+ +#+ #
-# +#+#+#+#+#+ +#+ #
-# Created: 2020/09/27 17:49:41 by charles #+# #+# #
-# Updated: 2020/09/30 15:02:10 by cacharle ### ########.fr #
-# #
-# ############################################################################ #
-
-import re
-import enum
-import itertools
-
-import test.error as error
-from helper import current_ms
-
-class Event(enum.Enum):
- FORK = 1
- EATING = 2
- SLEEPING = 3
- THINKING = 4
- DIED = 5
- NONE = 6
-
- @staticmethod
- def from_string(representation: str) -> Event:
- return {
- "has taken fork": Event.FORK,
- "is thinking": Event.THINKING,
- "is eating": Event.EATING,
- "is sleeping": Event.SLEEPING,
- "died": Event.DIED,
- }[representation]
-
- @staticmethod
- def to_string(event: Event) -> str:
- return {
- Event.FORK: "has taken fork",
- Event.THINKING: "is thinking",
- Event.EATING: "is eating",
- Event.SLEEPING: "is sleeping",
- Event.DIED: "died"
- }[event]
-
-
-
-class Log:
- def __init__(self, line: str, philo_num, start_time):
- match = re.match(
- r"^(?P<timestamp>\d+) "
- r"(?P<id>\d+) "
- r"(?P<event>is thinking|is eating|is sleeping|died|has taken fork)$",
- line
- )
- if match is None:
- raise error.Format(line, "wrong format")
-
- self._line = line
- self.id = self._parse_ranged_int(match.group("id"), 1, philo_num)
- self.timestamp = self._parse_ranged_int(
- match.group("timestamp"), start_time, current_ms())
-
- self.event = Event.from_string(match.group('event'))
-
- def _parse_ranged_int(self, s, lo, hi):
- try:
- value = int(s)
- if not (lo <= value <= hi):
- raise error.Format(self._line,
- "{} should be between {} - {}".format(s, lo, hi))
- except ValueError:
- raise error.Format(self._line, "{} sould be an integer".format(s))
- return value
-
- def __repr__(self):
- return "{}ms #{} {}".format(self.timestamp, self.id, self.event)
-
-
-class Philo:
- def __init__(
- self,
- id_: int,
- timeout_die: int,
- timeout_eat: int,
- timeout_sleep: int,
- meal_num: int
- ):
- self._logs = []
- self.id = id_
- self._timeout_die = timeout_die
- self._timeout_eat = timeout_eat
- self._timeout_sleep = timeout_sleep
- self._meal_num = meal_num
-
- def add_log(self, log):
- self._logs.append(log)
-
- def check(self):
- if len(self._logs) == 0:
- return
- grouped = [(e, list(g)) for e, g in itertools.groupby(self._logs, (lambda x: x.event))]
- for e, g in grouped:
- if e is Event.EATING:
- if len(g) != self._meal_num:
- raise error.Log(self._logs, "should eat {} times".format(self._meal_num))
- else:
- if len(g) != 1:
- raise error.Log(self._logs, "event {} should occur 1 time".format(Event.to_string(e)))
-
- # events = [e for e, _ in grouped]
- for l1, l2 in zip(self._logs, self._logs[1:]):
- if l2.event is Event.DIED:
- break
- if l1.event is Event.EATING and l2.event is Event.EATING:
- if l2.timestamp - l1.timestamp > self._timeout_eat:
- raise ValueError
- second, timeout = {
- Event.THINKING: (Event.EATING, None),
- Event.EATING: (Event.SLEEPING, self._timeout_eat),
- Event.SLEEPING: (Event.THINKING, self._timeout_sleep)
- }[l1.event]
- if l2.event is not second:
- raise error.Log(self._logs, "invalid switch {} -> {}".format(l1.event, l2.event))
- if timeout is not None and l2.timestamp - l1.timestamp > timeout:
- raise ValueError
-
- last_eat = None
- for log in reversed(self._logs):
- if log.event is Event.EATING:
- last_eat = log
- break
- last = self._logs[-1]
- if last_eat is not None and last_eat is not last:
- if last.timestamp - last_eat.timestamp > self._timeout_die + 10:
- raise error.Log(self._logs, "{} should be dead {} - {} > {}".format(
- self.id, last.timestamp, last_eat.timestamp, self._timeout_die + 10))
-
- def _check_fork_taking(self):
- for l1, l2, l3 in zip(self._logs, self._logs[1:], self._logs[2:]):
- if l1.event is Event.FORK and (l2.event is not Event.FORK or l2.event is not Event.EAT):
- raise ValueError("take fork but no eat")
-
- def _check_meal(self):
- pass
-
- def _check_order(self):
- pass
-
-
- @property
- def last_event(self):
- if len(self._logs) == 0:
- return Event.NONE
- return self._logs[-1].event
-
-
-class Table:
- def __init__(
- self,
- philo_num: int,
- timeout_die: int,
- timeout_eat: int,
- timeout_sleep: int,
- meal_num: int
- ):
- self._philos = [Philo(id_, timeout_die, timeout_eat, timeout_sleep, meal_num)
- for id_ in range(1, philo_num + 1)]
- self._logs = []
- self._philo_num = philo_num
- self.dead = False
-
- def add_log(self, log):
- self._logs.append(log)
- philo = next(p for p in self._philos if p.id == log.id)
- philo.add_log(log)
- if self.dead:
- raise error.Log(self._logs, "should not output after death")
- if log.event is Event.DIED:
- self.dead = True
-
- def check(self):
- if self.dead:
- return
- fork_used = 2 * len([p for p in self._philos if p.last_event == Event.EATING])
- if fork_used > self._philo_num:
- raise error.Log(self._logs, "using nonexistant forks")
- for l1, l2 in zip(self._logs, self._logs[1:]):
- if l1.timestamp > l2.timestamp:
- raise error.Log(self._logs, "timestamp not in ordered")
- for p in self._philos:
- p.check()