From ae79190f3a51fa7d3ec5f09e6a70ac5fb72c3550 Mon Sep 17 00:00:00 2001
From: volas <volas@ya.ru>
Date: Tue, 7 Jan 2025 16:49:43 +0300
Subject: [PATCH 1/5] online milestones

---
 code/__DEFINES/bridge.dm               |  1 +
 code/controllers/configuration.dm      |  2 +
 code/controllers/subsystem/samosbor.dm | 61 ++++++++++++++++++++++++++
 taucetistation.dme                     |  1 +
 4 files changed, 65 insertions(+)
 create mode 100644 code/controllers/subsystem/samosbor.dm

diff --git a/code/__DEFINES/bridge.dm b/code/__DEFINES/bridge.dm
index 54140a9dd07..425927b56c2 100644
--- a/code/__DEFINES/bridge.dm
+++ b/code/__DEFINES/bridge.dm
@@ -5,6 +5,7 @@
 #define BRIDGE_ROUNDSTAT  "roundstat"  //shuttle/server starting/round starting
 #define BRIDGE_SERVICE    "service"    //private debug msgs
 #define BRIDGE_ANNOUNCE   "announce"   //general announces for players
+#define BRIDGE_SAMOSBOR   "samosbor"   //online milestones notifications
 
 //admin
 #define BRIDGE_ADMINCOM       "admincom"       //admin faxes and command console
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index 740be68a39a..cc20110db68 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -233,6 +233,8 @@ var/global/bridge_secret = null
 	var/hard_deletes_overrun_threshold = 0.5
 	var/hard_deletes_overrun_limit = 0
 
+	var/samosbor = TRUE
+
 /datum/configuration/New()
 	for (var/type in subtypesof(/datum/game_mode))
 		var/datum/game_mode/M = type
diff --git a/code/controllers/subsystem/samosbor.dm b/code/controllers/subsystem/samosbor.dm
new file mode 100644
index 00000000000..8c5bd629c13
--- /dev/null
+++ b/code/controllers/subsystem/samosbor.dm
@@ -0,0 +1,61 @@
+#define SAMOSBOR_CACHE_FOLDER "cache/samosbor"
+#define SAMOSBOR_CACHE_PATH(suffix) "[SAMOSBOR_CACHE_FOLDER]/milestones_[suffix].txt"
+
+SUBSYSTEM_DEF(samosbor)
+	name = "Samosbor"
+	init_order = SS_INIT_DEFAULT
+	flags = SS_NO_FIRE
+
+	var/current_milestone = 10 // also as first milestone
+	var/milestone_step = 10
+
+	var/day
+	var/notfication_timer
+
+/datum/controller/subsystem/samosbor/Initialize()
+	if(!config.samosbor)
+		return ..()
+
+	day = time2text(world.realtime, "YYYY_MM_DD")
+
+	var/cache_path = SAMOSBOR_CACHE_PATH(day)
+	if(fexists(cache_path))
+		var/cached_milestone = text2num(trim(file2text(cache_path)))
+
+		if(isnum(cached_milestone) && cached_milestone >= (current_milestone + milestone_step))
+			current_milestone = cached_milestone
+		else
+			fdel(cache_path)
+
+	RegisterSignal(SSdcs, COMSIG_GLOB_CLIENT_CONNECT, PROC_REF(client_connected))
+
+	return ..()
+
+/datum/controller/subsystem/samosbor/proc/client_connected(datum/source, client/connected)
+	SIGNAL_HANDLER
+
+	var/players_online = length(global.clients)
+	if(players_online >= current_milestone)
+		INVOKE_ASYNC(src, PROC_REF(milestone_reached), players_online)
+
+/datum/controller/subsystem/samosbor/proc/milestone_reached(players_online)
+	world.log << "players_online [players_online]"
+
+	current_milestone = max(current_milestone, players_online - (players_online % milestone_step))
+
+	var/cache_path = SAMOSBOR_CACHE_PATH(day)
+	fdel(cache_path)
+	text2file(num2text(current_milestone), cache_path) // note: delete previous days files, todo or do it with host tools
+
+	// 30 seconds timer so we don't spam it at the start of the round
+	notfication_timer = addtimer(CALLBACK(src, PROC_REF(milestone_notification), current_milestone), 30 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
+
+/datum/controller/subsystem/samosbor/proc/milestone_notification(milestone)
+	world.send2bridge(
+		type = list(BRIDGE_ANNOUNCE, BRIDGE_SAMOSBOR),
+		attachment_title = "New today's milestone reached: more than **[milestone]** players!",
+		attachment_msg = "Join now: <[BYOND_JOIN_LINK]>"
+	)
+
+#undef SAMOSBOR_CACHE_FOLDER
+#undef SAMOSBOR_CACHE_PATH
diff --git a/taucetistation.dme b/taucetistation.dme
index 5c05db0c28c..25e5da510f4 100644
--- a/taucetistation.dme
+++ b/taucetistation.dme
@@ -266,6 +266,7 @@
 #include "code\controllers\subsystem\round_aspects.dm"
 #include "code\controllers\subsystem\round_rating.dm"
 #include "code\controllers\subsystem\runechat.dm"
+#include "code\controllers\subsystem\samosbor.dm"
 #include "code\controllers\subsystem\shuttles.dm"
 #include "code\controllers\subsystem\smartlight.dm"
 #include "code\controllers\subsystem\spacedrift.dm"

From bfb114e8f28abd2f057631d7e459f62fe4c42a55 Mon Sep 17 00:00:00 2001
From: volas <volas@ya.ru>
Date: Tue, 7 Jan 2025 19:09:31 +0300
Subject: [PATCH 2/5] fix

---
 code/controllers/subsystem/samosbor.dm | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/code/controllers/subsystem/samosbor.dm b/code/controllers/subsystem/samosbor.dm
index 8c5bd629c13..52e852c3453 100644
--- a/code/controllers/subsystem/samosbor.dm
+++ b/code/controllers/subsystem/samosbor.dm
@@ -6,7 +6,7 @@ SUBSYSTEM_DEF(samosbor)
 	init_order = SS_INIT_DEFAULT
 	flags = SS_NO_FIRE
 
-	var/current_milestone = 10 // also as first milestone
+	var/next_milestone = 10 // players online when we send the next notification
 	var/milestone_step = 10
 
 	var/day
@@ -22,8 +22,8 @@ SUBSYSTEM_DEF(samosbor)
 	if(fexists(cache_path))
 		var/cached_milestone = text2num(trim(file2text(cache_path)))
 
-		if(isnum(cached_milestone) && cached_milestone >= (current_milestone + milestone_step))
-			current_milestone = cached_milestone
+		if(isnum(cached_milestone) && cached_milestone >= (next_milestone + milestone_step))
+			next_milestone = cached_milestone
 		else
 			fdel(cache_path)
 
@@ -35,20 +35,18 @@ SUBSYSTEM_DEF(samosbor)
 	SIGNAL_HANDLER
 
 	var/players_online = length(global.clients)
-	if(players_online >= current_milestone)
+	if(players_online >= next_milestone)
 		INVOKE_ASYNC(src, PROC_REF(milestone_reached), players_online)
 
 /datum/controller/subsystem/samosbor/proc/milestone_reached(players_online)
-	world.log << "players_online [players_online]"
-
-	current_milestone = max(current_milestone, players_online - (players_online % milestone_step))
+	next_milestone = max(next_milestone, players_online - (players_online % milestone_step)) + milestone_step
 
 	var/cache_path = SAMOSBOR_CACHE_PATH(day)
 	fdel(cache_path)
-	text2file(num2text(current_milestone), cache_path) // note: delete previous days files, todo or do it with host tools
+	text2file(num2text(next_milestone), cache_path) // note: delete previous days files, todo or do it with host tools
 
 	// 30 seconds timer so we don't spam it at the start of the round
-	notfication_timer = addtimer(CALLBACK(src, PROC_REF(milestone_notification), current_milestone), 30 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
+	notfication_timer = addtimer(CALLBACK(src, PROC_REF(milestone_notification), next_milestone), 30 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
 
 /datum/controller/subsystem/samosbor/proc/milestone_notification(milestone)
 	world.send2bridge(

From f596c02604e2c6313707b368f0ef6089bd24b902 Mon Sep 17 00:00:00 2001
From: volas <volas@ya.ru>
Date: Tue, 7 Jan 2025 19:41:10 +0300
Subject: [PATCH 3/5] fix

---
 code/controllers/subsystem/samosbor.dm | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/code/controllers/subsystem/samosbor.dm b/code/controllers/subsystem/samosbor.dm
index 52e852c3453..2316b0cd7ce 100644
--- a/code/controllers/subsystem/samosbor.dm
+++ b/code/controllers/subsystem/samosbor.dm
@@ -39,19 +39,20 @@ SUBSYSTEM_DEF(samosbor)
 		INVOKE_ASYNC(src, PROC_REF(milestone_reached), players_online)
 
 /datum/controller/subsystem/samosbor/proc/milestone_reached(players_online)
-	next_milestone = max(next_milestone, players_online - (players_online % milestone_step)) + milestone_step
+	var/current_milestone = max(next_milestone, players_online - (players_online % milestone_step))
+	next_milestone = current_milestone + milestone_step
 
 	var/cache_path = SAMOSBOR_CACHE_PATH(day)
 	fdel(cache_path)
 	text2file(num2text(next_milestone), cache_path) // note: delete previous days files, todo or do it with host tools
 
 	// 30 seconds timer so we don't spam it at the start of the round
-	notfication_timer = addtimer(CALLBACK(src, PROC_REF(milestone_notification), next_milestone), 30 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
+	notfication_timer = addtimer(CALLBACK(src, PROC_REF(milestone_notification), current_milestone), 30 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
 
 /datum/controller/subsystem/samosbor/proc/milestone_notification(milestone)
 	world.send2bridge(
 		type = list(BRIDGE_ANNOUNCE, BRIDGE_SAMOSBOR),
-		attachment_title = "New today's milestone reached: more than **[milestone]** players!",
+		attachment_title = "New today's milestone reached: more than **[milestone]** players online!",
 		attachment_msg = "Join now: <[BYOND_JOIN_LINK]>"
 	)
 

From e0eb4835a4db3161a0e029b6bf0b2e7af2029cca Mon Sep 17 00:00:00 2001
From: volas <volas@ya.ru>
Date: Fri, 10 Jan 2025 12:03:43 +0300
Subject: [PATCH 4/5] translation

---
 code/controllers/subsystem/samosbor.dm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/code/controllers/subsystem/samosbor.dm b/code/controllers/subsystem/samosbor.dm
index 2316b0cd7ce..0fc793026bc 100644
--- a/code/controllers/subsystem/samosbor.dm
+++ b/code/controllers/subsystem/samosbor.dm
@@ -52,8 +52,8 @@ SUBSYSTEM_DEF(samosbor)
 /datum/controller/subsystem/samosbor/proc/milestone_notification(milestone)
 	world.send2bridge(
 		type = list(BRIDGE_ANNOUNCE, BRIDGE_SAMOSBOR),
-		attachment_title = "New today's milestone reached: more than **[milestone]** players online!",
-		attachment_msg = "Join now: <[BYOND_JOIN_LINK]>"
+		attachment_title = "Новый результат на сегодня: более [milestone] игроков онлайн!",
+		attachment_msg = BRIDGE_JOIN_LINKS
 	)
 
 #undef SAMOSBOR_CACHE_FOLDER

From b7c95d92645ca7098a669063c1f5d92ba064ce56 Mon Sep 17 00:00:00 2001
From: volas <volas@ya.ru>
Date: Fri, 10 Jan 2025 12:07:11 +0300
Subject: [PATCH 5/5] finalize

---
 code/controllers/configuration.dm      | 2 --
 code/controllers/subsystem/samosbor.dm | 2 +-
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index cc20110db68..740be68a39a 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -233,8 +233,6 @@ var/global/bridge_secret = null
 	var/hard_deletes_overrun_threshold = 0.5
 	var/hard_deletes_overrun_limit = 0
 
-	var/samosbor = TRUE
-
 /datum/configuration/New()
 	for (var/type in subtypesof(/datum/game_mode))
 		var/datum/game_mode/M = type
diff --git a/code/controllers/subsystem/samosbor.dm b/code/controllers/subsystem/samosbor.dm
index 0fc793026bc..9ed2ee4d762 100644
--- a/code/controllers/subsystem/samosbor.dm
+++ b/code/controllers/subsystem/samosbor.dm
@@ -13,7 +13,7 @@ SUBSYSTEM_DEF(samosbor)
 	var/notfication_timer
 
 /datum/controller/subsystem/samosbor/Initialize()
-	if(!config.samosbor)
+	if(!config.chat_bridge)
 		return ..()
 
 	day = time2text(world.realtime, "YYYY_MM_DD")