Compare commits

..

1 Commits

Author SHA1 Message Date
919bb59859
reviewstats: don't write 'None' if duration is unset
Keep the current reviewstats format: when review duration is unset/unknown,
the line contains only two values separated by one tab and then EOL.

Another way to test/reproduce the fixed issue:
1. add 'lllll : !stats' to tests/datas/irc.txt
2. run 'pytest tests/test_review_stats.py'
2024-07-21 15:18:52 +02:00
12 changed files with 49 additions and 182 deletions

View File

@ -15,7 +15,7 @@ import settings
class HebdoBot(IrcBot): class HebdoBot(IrcBot):
def __init__(self, settings): def __init__(self, settings):
super().__init__(settings) super().__init__(settings)
self.VERSION = "3.1.0" self.VERSION = "3.0.0"
self.review = Review() self.review = Review()
for event in events: for event in events:
@ -65,7 +65,7 @@ class HebdoBot(IrcBot):
""" """
channel = event.target channel = event.target
sender = event.source.nick sender = event.source.nick
message = event.arguments[0].strip() message = event.arguments[0]
if self.review.is_started: if self.review.is_started:
self.review.add_message(sender, message) self.review.add_message(sender, message)

View File

@ -3,7 +3,6 @@ from .bad_command import BadCommand
from .cancel_previous_input import CancelPreviousInput from .cancel_previous_input import CancelPreviousInput
from .collective_subject import CollectiveSubject from .collective_subject import CollectiveSubject
from .comment import Comment from .comment import Comment
from .completion import Completion
from .chrono import Chrono from .chrono import Chrono
from .current import Current from .current import Current
from .date import Date from .date import Date
@ -37,7 +36,6 @@ hooks = (
Help(), Help(),
IndividualSubject(), IndividualSubject(),
Missing(), Missing(),
Completion(),
Record(), Record(),
StartReview(), StartReview(),
StopReview(), StopReview(),

View File

@ -1,44 +0,0 @@
import logger
class Completion:
def process(self, bot, channel, sender, message):
"""
Si la commande est bonne, le bot renvoie la liste des personnes ayant participé
au sujet en cours mais n'ayant pas encore fini (commentaire %fini ou % fini).
"""
if message.lower() == "!complet":
logger.info("!complet caught.")
if not bot.review.is_started:
bot.send(channel, f"{sender}, pas de revue en cours.")
return True
if bot.review.current_topic is None:
bot.send(channel, "% Pas de sujet en cours.")
return True
participants = bot.review.current_topic.participants
find_text = f"# {bot.review.current_topic.title}"
if bot.review.current_topic.collective:
find_text = "#" + find_text
text_found = False
for message in bot.review.messages:
if text_found:
if message.text in ("%fini", "% fini", "%ras", "% ras"):
participants = list(set(participants) - set((message.author,)))
if find_text == message.text:
text_found = True
if participants == []:
bot.send(
channel,
"% Tout le monde a terminé de s'exprimer sur le sujet courant \\o/",
)
else:
bot.send(
channel,
"% Personnes n'ayant pas encore terminé de s'exprimer sur le "
f"sujet courant : {', '.join(participants)}",
)
return True

View File

@ -30,9 +30,9 @@ class Help:
" !fin : terminer la revue en cours", " !fin : terminer la revue en cours",
" !stop  : abandonner la revue en cours", " !stop  : abandonner la revue en cours",
" ", " ",
"Autres commandes : !anniv, !bonjour, !chrono, !complet, !date, " "Autres commandes : !anniv, !bonjour, !chrono, !date, !hello, "
"!hello, !licence, !manquantes, !merci, !record, !salut, !stats, " "!licence, !manquantes, !merci, !record, !salut, !stats, !status, "
"!status, !version", "!version",
), ),
) )

View File

@ -6,7 +6,7 @@ class StopReview:
""" """
Si la commande est bonne, le bot abandonne la revue hebdomadaire en cours. Si la commande est bonne, le bot abandonne la revue hebdomadaire en cours.
""" """
if message.lower() == "!stop": if message.lower() in ("!stop"):
logger.info("!stop caught.") logger.info("!stop caught.")
if not bot.review.is_started: if not bot.review.is_started:

View File

@ -9,6 +9,29 @@ class ReviewData:
user_count: int user_count: int
duration: int duration: int
def __str__(self):
return (
f"{self.date.strftime('%Y%m%d-%Hh%M')}\t{self.user_count}"
f"{f'\t{self.duration}' if self.duration is not None else ''}"
"\n"
)
@staticmethod
def load(line: str):
datas = re.split(r"\s+", line.strip())
if len(datas) == 2:
return ReviewData(
datetime.strptime(datas[0], "%Y%m%d-%Hh%M"),
int(datas[1]),
None,
)
return ReviewData(
datetime.strptime(datas[0], "%Y%m%d-%Hh%M"),
int(datas[1]),
int(datas[2]),
)
class Board: class Board:
def __init__(self, datas={}): def __init__(self, datas={}):
@ -148,23 +171,7 @@ class ReviewStats:
lines = file_handle.read().splitlines() lines = file_handle.read().splitlines()
for line in lines: for line in lines:
if line.strip() != "": if line.strip() != "":
datas = re.split(r"\s+", line) self.datas.append(ReviewData.load(line))
if len(datas) == 2:
self.datas.append(
ReviewData(
datetime.strptime(datas[0], "%Y%m%d-%Hh%M"),
int(datas[1]),
None,
)
)
else:
self.datas.append(
ReviewData(
datetime.strptime(datas[0], "%Y%m%d-%Hh%M"),
int(datas[1]),
int(datas[2]) if datas[2]!="" else None,
)
)
except FileNotFoundError: except FileNotFoundError:
# no file, no stats # no file, no stats
pass pass
@ -174,10 +181,4 @@ class ReviewStats:
def save(self): def save(self):
with open(self.filepath, "w") as file_handle: with open(self.filepath, "w") as file_handle:
for data in self.datas: for data in self.datas:
duration = "" file_handle.write(str(data))
if data.duration is not None:
duration = f"\t{data.duration}"
file_handle.write(
f"{data.date.strftime('%Y%m%d-%Hh%M')}\t"
f"{data.user_count}{duration}\n"
)

View File

@ -10,11 +10,3 @@ def test_private_command(bot):
bot.test_private_message(bot.channel, SENDER, "!hello") bot.test_private_message(bot.channel, SENDER, "!hello")
assert len(bot.answers) == 1 assert len(bot.answers) == 1
assert bot.answers[0].message == "Vos commandes dans le salon public" assert bot.answers[0].message == "Vos commandes dans le salon public"
def test_public_message(bot):
# Cheating here to save message sent
bot.review.started = True
bot.test_public_message(bot.channel, SENDER, " hello ")
assert len(bot.answers) == 0
assert bot.review.messages[0].text == "hello"

View File

@ -1,7 +1,6 @@
from datetime import datetime from datetime import datetime
import shutil import shutil
from review.stats import ReviewStats
from tests.utils import bot, OWNER, SENDER from tests.utils import bot, OWNER, SENDER
@ -53,38 +52,3 @@ def test_other_review(bot):
with open("tests/reviews/20240402-log-irc-revue-hebdomadaire.txt") as file_handle: with open("tests/reviews/20240402-log-irc-revue-hebdomadaire.txt") as file_handle:
content_tested = file_handle.read() content_tested = file_handle.read()
assert content_ok in content_tested assert content_ok in content_tested
def test_fast_review(bot):
bot.test_public_message(bot.channel, "lllll", "!start")
bot.test_public_message(bot.channel, "lllll", "# new test")
bot.test_public_message(bot.channel, "lllll", "test")
bot.test_public_message(bot.channel, "lllll", "!fin")
bot.test_public_message(bot.channel, "lllll", "!stats")
def test_review_with_one_user_dont_update_stats(bot):
review = ReviewStats("tests/reviews/reviewstats.csv")
review.load()
size = review.size
bot.test_public_message(bot.channel, "lllll", "!start")
bot.test_public_message(bot.channel, "lllll", "# new test")
bot.test_public_message(bot.channel, "lllll", "test")
bot.test_public_message(bot.channel, "lllll", "!fin")
review = ReviewStats("tests/reviews/reviewstats.csv")
review.load()
assert review.size == size
def test_review_with_two_user_update_stats(bot):
review = ReviewStats("tests/reviews/reviewstats.csv")
review.load()
size = review.size
bot.test_public_message(bot.channel, "lllll", "!start")
bot.test_public_message(bot.channel, "lllll", "# new test")
bot.test_public_message(bot.channel, "lllll", "test")
bot.test_public_message(bot.channel, "ooooo", "another test")
bot.test_public_message(bot.channel, "lllll", "!fin")
review = ReviewStats("tests/reviews/reviewstats.csv")
review.load()
assert review.size == (size + 1)

View File

@ -0,0 +1,8 @@
from review.stats import ReviewData
def test_reviewdata():
for filename in ("reviewstats_1.csv", "reviewstats_2.csv"):
with open(f"tests/datas/{filename}", "r") as review:
for line in review:
assert line == str(ReviewData.load(line))

View File

@ -1,7 +1,7 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
import shutil import shutil
from tests.utils import bot, OWNER, SENDER, SENDER_2 from tests.utils import bot, OWNER, SENDER
def setup_function(): def setup_function():
@ -515,54 +515,3 @@ def test_finish_review_no_participation(bot):
bot.test_public_message(bot.channel, OWNER, "!fin") bot.test_public_message(bot.channel, OWNER, "!fin")
assert len(bot.answers) == 1 assert len(bot.answers) == 1
assert bot.answers[0].message == "Participation nulle détectée. La revue est ignorée." assert bot.answers[0].message == "Participation nulle détectée. La revue est ignorée."
def test_simple_completion_on_topic(bot):
bot.test_public_message(bot.channel, OWNER, "!start")
bot.test_public_message(bot.channel, OWNER, "# individual topic")
bot.test_public_message(bot.channel, OWNER, "Owner message on individual topic")
bot.test_public_message(bot.channel, SENDER, "Sender message on individual topic")
bot.test_public_message(bot.channel, SENDER_2, "Sender_2 message on individual topic")
bot.test_public_message(bot.channel, OWNER, "## collective topic")
bot.test_public_message(bot.channel, OWNER, "Owner message on collective topic")
bot.test_public_message(bot.channel, SENDER, "Sender message on collective topic")
bot.test_public_message(bot.channel, OWNER, "!complet")
assert len(bot.answers) == 1
assert SENDER_2 not in bot.answers[0].message[76:]
assert SENDER in bot.answers[0].message[76:]
assert OWNER in bot.answers[0].message[76:]
def test_semi_completion_on_topic(bot):
bot.test_public_message(bot.channel, OWNER, "!start")
bot.test_public_message(bot.channel, OWNER, "# individual topic")
bot.test_public_message(bot.channel, OWNER, "Owner message on individual topic")
bot.test_public_message(bot.channel, SENDER, "Sender message on individual topic")
bot.test_public_message(bot.channel, SENDER_2, "Sender_2 message on individual topic")
bot.test_public_message(bot.channel, OWNER, "## collective topic")
bot.test_public_message(bot.channel, OWNER, "Owner message on collective topic")
bot.test_public_message(bot.channel, SENDER, "Sender message on collective topic")
bot.test_public_message(bot.channel, SENDER_2, "%ras")
bot.test_public_message(bot.channel, SENDER, "%fini")
bot.test_public_message(bot.channel, OWNER, "!complet")
assert len(bot.answers) == 1
assert SENDER_2 not in bot.answers[0].message[76:]
assert SENDER not in bot.answers[0].message[76:]
assert OWNER in bot.answers[0].message[76:]
def test_total_completion_on_topic(bot):
bot.test_public_message(bot.channel, OWNER, "!start")
bot.test_public_message(bot.channel, OWNER, "# individual topic")
bot.test_public_message(bot.channel, OWNER, "Owner message on individual topic")
bot.test_public_message(bot.channel, SENDER, "Sender message on individual topic")
bot.test_public_message(bot.channel, SENDER_2, "Sender_2 message on individual topic")
bot.test_public_message(bot.channel, OWNER, "## collective topic")
bot.test_public_message(bot.channel, OWNER, "Owner message on collective topic")
bot.test_public_message(bot.channel, SENDER, "Sender message on collective topic")
bot.test_public_message(bot.channel, SENDER_2, "%ras")
bot.test_public_message(bot.channel, SENDER, "%fini")
bot.test_public_message(bot.channel, OWNER, "% fini")
bot.test_public_message(bot.channel, OWNER, "!complet")
assert len(bot.answers) == 1
assert SENDER_2 + "," not in bot.answers[0].message[76:]
assert SENDER + "," not in bot.answers[0].message[76:]
assert OWNER + "," not in bot.answers[0].message[76:]

View File

@ -7,7 +7,6 @@ from tests import settings
OWNER = "me" OWNER = "me"
SENDER = "foobar" SENDER = "foobar"
SENDER_2 = "foobaz"
@dataclass @dataclass