afk manager

This commit is contained in:
Nordup 2025-08-17 16:47:53 +07:00
parent 9598ec94f0
commit 99d7c51b5f
7 changed files with 112 additions and 5 deletions

View file

@ -35,6 +35,7 @@ Debug="*res://scripts/debug_log/debug.gd"
AnalyticsEvents="*res://scripts/api/analytics/analytics_events.gd"
Backend="*res://scripts/api/backend.gd"
Navigation="*res://scenes/autoloads/navigation.tscn"
AfkManager="*res://scripts/afk_manager.gd"
[debug]

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=20 format=3 uid="uid://ct8gsph3wnepl"]
[gd_scene load_steps=21 format=3 uid="uid://ct8gsph3wnepl"]
[ext_resource type="Script" path="res://scripts/app.gd" id="1_skc7d"]
[ext_resource type="Resource" uid="uid://b1xvdym0qh6td" path="res://resources/gate_events.res" id="2_cdryv"]
@ -19,6 +19,7 @@
[ext_resource type="Script" path="res://scripts/api/analytics/analytics_sender_onboarding.gd" id="15_a11br"]
[ext_resource type="Script" path="res://scripts/api/featured_gates.gd" id="15_c1fxl"]
[ext_resource type="Resource" uid="uid://crjhix0osmtnf" path="res://resources/ui_events.res" id="16_6u24i"]
[ext_resource type="Script" path="res://scripts/api/analytics/analytics_sender_afk.gd" id="17_xfh2c"]
[node name="App" type="Node" node_paths=PackedStringArray("scenes_root")]
script = ExtResource("1_skc7d")
@ -63,6 +64,9 @@ bookmarks = ExtResource("6_rupvx")
script = ExtResource("15_a11br")
ui_events = ExtResource("16_6u24i")
[node name="SenderAfk" type="Node" parent="Api/Analytics"]
script = ExtResource("17_xfh2c")
[node name="DiscoverGate" type="Node" parent="Api"]
script = ExtResource("13_3xhql")
api = ExtResource("10_04o5h")

View file

@ -0,0 +1,60 @@
extends Node
#class_name AfkManager
signal state_changed(is_afk: bool)
const AFK_TIMEOUT_SEC = 180
var afk_check_timer: Timer
var session_start_tick: int
var last_key_tick: int
var cumulative_afk_msec: int
var afk_start_tick: int
func _ready() -> void:
session_start_tick = Time.get_ticks_msec()
last_key_tick = session_start_tick
afk_check_timer = Timer.new()
afk_check_timer.one_shot = false
afk_check_timer.wait_time = 1.0
add_child(afk_check_timer)
afk_check_timer.timeout.connect(check_afk)
afk_check_timer.start()
func _input(_event: InputEvent) -> void:
var now := Time.get_ticks_msec()
last_key_tick = now
if afk_start_tick != 0:
leave_afk(now)
func check_afk() -> void:
var now := Time.get_ticks_msec()
if afk_start_tick == 0 and now - last_key_tick >= AFK_TIMEOUT_SEC * 1000:
enter_afk(now)
func enter_afk(now: int) -> void:
afk_start_tick = now
state_changed.emit(true)
func leave_afk(now: int) -> void:
if afk_start_tick == 0:
return
cumulative_afk_msec += now - afk_start_tick
afk_start_tick = 0
state_changed.emit(false)
func get_active_sec() -> float:
var now := Time.get_ticks_msec()
var afk_current := (now - afk_start_tick) if afk_start_tick != 0 else 0
var active_msec := (now - session_start_tick) - cumulative_afk_msec - afk_current
return max(0.0, float(active_msec) / 1000.0)

View file

@ -100,3 +100,15 @@ func onboarding_finished(time_spend: float) -> Dictionary:
var event = base("onboarding_finished")
event.time_spend = time_spend
return event
# AFK
func enter_afk() -> Dictionary:
return base("enter_afk")
func leave_afk(time_spend: float) -> Dictionary:
var event = base("leave_afk")
event.time_spend = time_spend
return event

View file

@ -0,0 +1,19 @@
extends AnalyticsSender
class_name AnalyticsSenderAfk
var afk_started_tick: int
func start() -> void:
super.start()
AfkManager.state_changed.connect(send_afk_state_changed)
func send_afk_state_changed(is_afk: bool) -> void:
if is_afk:
afk_started_tick = Time.get_ticks_msec()
analytics.send_event(AnalyticsEvents.enter_afk())
else:
var time_spend = Analytics.get_delta_sec_from_tick(afk_started_tick)
analytics.send_event(AnalyticsEvents.leave_afk(time_spend))

View file

@ -2,6 +2,7 @@ extends AnalyticsSender
class_name AnalyticsSenderApp
const HEARTBEAT_DELAY = 60
var heartbeat_timer: Timer
@ -9,7 +10,9 @@ func start() -> void:
super.start()
analytics.send_event(AnalyticsEvents.app_open())
start_heartbeat()
AfkManager.state_changed.connect(on_state_changed)
# Send latest exit event
var json: String = DataSaver.get_string("analytics", "app_exit")
@ -26,12 +29,20 @@ func start_heartbeat() -> void:
func send_hearbeat() -> void:
var time_spend = Analytics.get_delta_sec_from_tick(0)
var time_spend = AfkManager.get_active_sec()
analytics.send_event(AnalyticsEvents.heartbeat(time_spend))
func on_state_changed(is_afk: bool) -> void:
if is_afk:
heartbeat_timer.stop()
return
heartbeat_timer.start(HEARTBEAT_DELAY)
func _exit_tree() -> void:
# Save to send on open
var time_spend = Analytics.get_delta_sec_from_tick(0)
var time_spend = AfkManager.get_active_sec()
var event = AnalyticsEvents.app_exit(time_spend)
DataSaver.set_value("analytics", "app_exit", JSON.stringify(event))

View file

@ -1,7 +1,7 @@
extends Control
const SECTION: String = "onboarding"
const KEY: String = "shown"
const SECTION = "onboarding"
const KEY = "shown"
const INITIAL_DELAY = 1.0
const SHOWN = Color(1, 1, 1, 1)