Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions components/dashboard/tabs/PhysioNetworkBridge.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# components/dashboard/tabs/PhysioNetworkBridge.gd
extends Control

@onready var loading_label = $LoadingLabel
@onready var correlation_value = $MainGrid/ChartCard/ChartVBox/MetricsGrid/CorrelationValue
@onready var impact_factor_value = $MainGrid/ChartCard/ChartVBox/MetricsGrid/ImpactFactorValue
@onready var hrv_value = $MainGrid/GaugeCard/GaugeVBox/HRVValue
@onready var avg_coherence_value = $MainGrid/GaugeCard/GaugeVBox/AvgCoherenceValue
@onready var gauge = $MainGrid/GaugeCard/GaugeVBox/Gauge
@onready var chart = $MainGrid/ChartCard/ChartVBox/Chart
@onready var timer = $Timer

var history = []
var hrv_line = Line2D.new()
var coherence_line = Line2D.new()

func _ready():
timer.timeout.connect(_on_Timer_timeout)
loading_label.show()
$MainGrid.hide()

hrv_line.width = 2
hrv_line.default_color = Color(0.5, 0.5, 1.0)
chart.add_child(hrv_line)

coherence_line.width = 2
coherence_line.default_color = Color(0.5, 1.0, 0.5)
chart.add_child(coherence_line)

func _on_Timer_timeout():
var m = PhysioNetworkBridge.getPhysioNetworkMetrics()

if m:
if loading_label.visible:
loading_label.hide()
$MainGrid.show()

correlation_value.text = "%.2f" % m.correlation
impact_factor_value.text = "%.2f" % m.impactFactor
hrv_value.text = "%d ms" % m.hrv
avg_coherence_value.text = "%.1f %%" % (m.avgCoherence * 100)

var boostPct = round(((m.impactFactor - 0.8) / 0.4) * 100)
gauge.value = boostPct

history.push_back(m)
if history.size() > 60:
history.pop_front()

update_chart()

if m.correlation < 0.5:
print("[Bridge] Low correlation: %.2f" % m.correlation)

func update_chart():
hrv_line.clear_points()
coherence_line.clear_points()

var chart_width = chart.size.x
var chart_height = chart.size.y
var num_points = history.size()
var point_spacing = chart_width / (num_points - 1) if num_points > 1 else 0

for i in range(num_points):
var m = history[i]
var x = i * point_spacing

var hrv_y = chart_height - (m.hrv - 30) / (100 - 30) * chart_height
hrv_line.add_point(Vector2(x, hrv_y))

var coherence_y = chart_height - m.avgCoherence * chart_height
coherence_line.add_point(Vector2(x, coherence_y))
130 changes: 130 additions & 0 deletions components/dashboard/tabs/PhysioNetworkBridge.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
[gd_scene load_steps=2 format=3 uid="uid://dqe8v3j4n7w2k"]

[ext_resource type="Script" path="res://components/dashboard/tabs/PhysioNetworkBridge.gd" id="1_t8j7k"]

[node name="PhysioNetworkBridge" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_t8j7k")

[node name="Timer" type="Timer" parent="."]
autostart = true

[node name="LoadingLabel" type="Label" parent="."]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
text = "Loading bridge..."
horizontal_alignment = 1
vertical_alignment = 1

[node name="MainGrid" type="GridContainer" parent="."]
layout_mode = 0
anchor_right = 1.0
anchor_bottom = 1.0
columns = 3

[node name="ChartCard" type="PanelContainer" parent="MainGrid"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_stretch_ratio = 2.0

[node name="ChartVBox" type="VBoxContainer" parent="MainGrid/ChartCard"]
layout_mode = 2

[node name="ChartTitle" type="Label" parent="MainGrid/ChartCard/ChartVBox"]
layout_mode = 2
text = "HRV ↔ Network Coherence"

[node name="Chart" type="Control" parent="MainGrid/ChartCard/ChartVBox"]
layout_mode = 2
size_flags_vertical = 3

[node name="Legend" type="VBoxContainer" parent="MainGrid/ChartCard/ChartVBox"]
layout_mode = 2

[node name="HRVLegend" type="HBoxContainer" parent="MainGrid/ChartCard/ChartVBox/Legend"]
layout_mode = 2

[node name="HRVColor" type="ColorRect" parent="MainGrid/ChartCard/ChartVBox/Legend/HRVLegend"]
layout_mode = 2
custom_minimum_size = Vector2(20, 20)
color = Color(0.5, 0.5, 1, 1)

[node name="HRVLabel" type="Label" parent="MainGrid/ChartCard/ChartVBox/Legend/HRVLegend"]
layout_mode = 2
text = "HRV (ms)"

[node name="CoherenceLegend" type="HBoxContainer" parent="MainGrid/ChartCard/ChartVBox/Legend"]
layout_mode = 2

[node name="CoherenceColor" type="ColorRect" parent="MainGrid/ChartCard/ChartVBox/Legend/CoherenceLegend"]
layout_mode = 2
custom_minimum_size = Vector2(20, 20)
color = Color(0.5, 1, 0.5, 1)

[node name="CoherenceLabel" type="Label" parent="MainGrid/ChartCard/ChartVBox/Legend/CoherenceLegend"]
layout_mode = 2
text = "Coherence (%)"

[node name="MetricsGrid" type="GridContainer" parent="MainGrid/ChartCard/ChartVBox"]
layout_mode = 2
columns = 2

[node name="CorrelationLabel" type="Label" parent="MainGrid/ChartCard/ChartVBox/MetricsGrid"]
layout_mode = 2
text = "Correlation:"

[node name="CorrelationValue" type="Label" parent="MainGrid/ChartCard/ChartVBox/MetricsGrid"]
layout_mode = 2

[node name="ImpactFactorLabel" type="Label" parent="MainGrid/ChartCard/ChartVBox/MetricsGrid"]
layout_mode = 2
text = "Impact Factor:"

[node name="ImpactFactorValue" type="Label" parent="MainGrid/ChartCard/ChartVBox/MetricsGrid"]
layout_mode = 2

[node name="GaugeCard" type="PanelContainer" parent="MainGrid"]
layout_mode = 2
size_flags_horizontal = 3

[node name="GaugeVBox" type="VBoxContainer" parent="MainGrid/GaugeCard"]
layout_mode = 2
alignment = 1

[node name="GaugeTitle" type="Label" parent="MainGrid/GaugeCard/GaugeVBox"]
layout_mode = 2
text = "Physio Impact"
horizontal_alignment = 1

[node name="Gauge" type="TextureProgressBar" parent="MainGrid/GaugeCard/GaugeVBox"]
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
max_value = 100.0
step = 1.0
value = 50.0
fill_mode = 4

[node name="HRVLabel" type="Label" parent="MainGrid/GaugeCard/GaugeVBox"]
layout_mode = 2
text = "HRV:"
horizontal_alignment = 1

[node name="HRVValue" type="Label" parent="MainGrid/GaugeCard/GaugeVBox"]
layout_mode = 2
horizontal_alignment = 1

[node name="AvgCoherenceLabel" type="Label" parent="MainGrid/GaugeCard/GaugeVBox"]
layout_mode = 2
text = "Avg Coherence:"
horizontal_alignment = 1

[node name="AvgCoherenceValue" type="Label" parent="MainGrid/GaugeCard/GaugeVBox"]
layout_mode = 2
horizontal_alignment = 1
4 changes: 4 additions & 0 deletions core/avatar/avatar_ui.gd
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ signal existing_entity_selected(int)

@onready var ui := %TargetUI
@onready var ui_helper = get_node("/root/UIHelper")
@onready var physio_network_bridge = $PhysioNetworkBridge

var _ui
var avatar: LCAvatar
Expand Down Expand Up @@ -239,3 +240,6 @@ func _on_visibility_changed():
var parent = get_parent()
if parent and parent.get_parent() and parent.get_parent().has_method("get_entities"):
call_deferred("update_entities", parent.get_parent().get_entities())

func _on_PhysioNetworkBridgeButton_pressed():
physio_network_bridge.visible = !physio_network_bridge.visible
19 changes: 18 additions & 1 deletion core/avatar/avatar_ui.tscn
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[gd_scene load_steps=8 format=3 uid="uid://wdnxqhctneyv"]
[gd_scene load_steps=9 format=3 uid="uid://wdnxqhctneyv"]

[ext_resource type="Script" uid="uid://bpq5fqrtu7f5o" path="res://core/avatar/avatar_ui.gd" id="1_igs02"]
[ext_resource type="Theme" uid="uid://hve1e7mnexbi" path="res://themes/theme.tres" id="1_ois6a"]
[ext_resource type="PackedScene" uid="uid://dqe8v3j4n7w2k" path="res://components/dashboard/tabs/PhysioNetworkBridge.tscn" id="2_abcde"]

[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_entities_panel"]
content_margin_left = 16.0
Expand Down Expand Up @@ -87,6 +88,21 @@ mouse_filter = 2
theme = ExtResource("1_ois6a")
script = ExtResource("1_igs02")

[node name="PhysioNetworkBridgeButton" type="Button" parent="."]
layout_mode = 0
offset_right = 200.0
offset_bottom = 31.0
text = "Physio-Network Bridge"

[node name="PhysioNetworkBridge" parent="." instance=ExtResource("2_abcde")]
visible = false
layout_mode = 0
anchor_right = 0.0
anchor_bottom = 0.0
offset_left = 210.0
offset_right = 1110.0
offset_bottom = 600.0

[node name="EntityUserContainer" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 3
Expand Down Expand Up @@ -263,6 +279,7 @@ unique_name_in_owner = true
layout_mode = 2
underline = 2

[connection signal="pressed" from="PhysioNetworkBridgeButton" to="." method="_on_PhysioNetworkBridgeButton_pressed"]
[connection signal="item_selected" from="EntityUserContainer/UsersContainer/VBoxContainer/Users" to="." method="_on_users_item_selected"]
[connection signal="item_selected" from="EntityUserContainer/EntitiesContainer/VBoxContainer/Entities" to="." method="_on_entities_item_selected"]
[connection signal="pressed" from="WalletInfo/ConnectWallet" to="." method="_on_connect_wallet_pressed"]
Expand Down
28 changes: 28 additions & 0 deletions core/simulation/NetworkSimulator.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# core/simulation/NetworkSimulator.gd

class_name NetworkSimulator

# Placeholder for network nodes
var nodes = []

func _init():
# Initialize nodes here
for i in range(10):
nodes.append({"coherence": randf_range(0.5, 0.9)})

func update_connections():
# Update connections between nodes
pass

func updateWithPhysioInfluence(influence: float):
for n in nodes:
n.coherence = clamp(n.coherence * influence, 0.3, 1.0)
update_connections()

func get_avg_coherence() -> float:
if nodes.is_empty():
return 0.0
var sum = 0.0
for n in nodes:
sum += n.coherence
return sum / nodes.size()
71 changes: 71 additions & 0 deletions core/simulation/PhysioNetworkBridge.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# core/simulation/PhysioNetworkBridge.gd
extends Node

class_name PhysioNetworkBridge

# Define the data structure for physio-network metrics
class PhysioNetworkMetrics:
var hrv: float
var avgCoherence: float
var correlation: float
var impactFactor: float
var timestamp: int

func _init(p_hrv: float, p_avgCoherence: float, p_correlation: float, p_impactFactor: float, p_timestamp: int):
hrv = p_hrv
avgCoherence = p_avgCoherence
correlation = p_correlation
impactFactor = p_impactFactor
timestamp = p_timestamp

var physioHistory: Array[PhysioNetworkMetrics] = [] # Ring buffer
var network_simulator = NetworkSimulator.new()

# HRV influence calculator
func getHRVInfluence(hrv: float) -> float:
# 30-100 ms → 0.8-1.2 multiplicative factor
var clamped = clamp(hrv, 30.0, 100.0)
return 0.8 + ((clamped - 30.0) / 70.0) * 0.4

# Pearson r (quick util)
func calcCorrelation(history: Array[PhysioNetworkMetrics]) -> float:
if history.size() < 3:
return 0.0
var n = history.size()
var sumH = 0.0
var sumC = 0.0
var sumH2 = 0.0
var sumC2 = 0.0
var sumHC = 0.0
for m in history:
sumH += m.hrv
sumC += m.avgCoherence
sumH2 += m.hrv * m.hrv
sumC2 += m.avgCoherence * m.avgCoherence
sumHC += m.hrv * m.avgCoherence
var num = n * sumHC - sumH * sumC
var den = sqrt((n * sumH2 - sumH * sumH) * (n * sumC2 - sumC * sumC))
return den if den != 0.0 else 0.0

# New endpoint
func getPhysioNetworkMetrics() -> PhysioNetworkMetrics:
# Mock data for now
var vitals = {"hrv": 60.0 + randf_range(-5, 5)}
var influence = getHRVInfluence(vitals.hrv)

network_simulator.updateWithPhysioInfluence(influence)
var coherenceMetrics = {"avgCoherence": network_simulator.get_avg_coherence()}

var m = PhysioNetworkMetrics.new(
vitals.hrv,
coherenceMetrics.avgCoherence,
calcCorrelation(physioHistory),
influence,
Time.get_unix_time_from_system()
)

physioHistory.push_back(m)
if physioHistory.size() > 60: # 60 s sliding window
physioHistory.pop_front()

return m
2 changes: 1 addition & 1 deletion plug.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
extends "res://addons/gd-plug/plug.gd" ## it's the only addon to be added to git, the rest are managed by it

func _plugging():
pass
plug("fenix-hub/godot-engine.easy-charts")
#UI
# plug("folt-a/godot-idea-board")
# plug("imjp94/gd-plug-ui")
Expand Down
1 change: 1 addition & 0 deletions project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ ReplayManager="*res://core/singletones/replay-manager.gd"
ReplayShortcut="*res://core/singletones/replay-shortcut.gd"
NotificationManager="*res://core/singletones/notification-manager.gd"
UIHelper="*res://themes/ui_helper.gd"
PhysioNetworkBridge="*res://core/simulation/PhysioNetworkBridge.gd"

[display]

Expand Down