File size: 4,902 Bytes
fdcd9e5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""

ResearchRadar — SettingsScreen.



User-configurable interest keywords, ranking weights, and API keys.

All settings are persisted as JSON in the app data directory.

"""

from __future__ import annotations

import json
import logging
import os

from kivy.lang import Builder
from kivy.properties import (
    NumericProperty,
    ObjectProperty,
    StringProperty,
)
from kivy.uix.screenmanager import Screen

logger = logging.getLogger(__name__)

_KV_PATH = os.path.join(os.path.dirname(__file__), 'kv', 'settings.kv')
if os.path.exists(_KV_PATH):
    Builder.load_file(_KV_PATH)

_DEFAULT_SETTINGS = {
    'interests': {
        'ml': 'deep learning transformers attention',
        'ai': 'artificial intelligence language models',
        'cs': 'software engineering algorithms',
        'neuroscience': 'synaptic plasticity cortex neurons',
        'bci': 'brain computer interface EEG decoding',
    },
    'weight_relevance': 0.60,
    'weight_citation': 0.30,
    'weight_recency': 0.10,
    'top_n': 5,
    'schedule_day': 'sun',
    'schedule_hour': 8,
    'semantic_scholar_key': '',
    'pubmed_key': '',
}


class SettingsScreen(Screen):
    """Settings screen with interest keywords, weights, and API keys."""

    # Interest text fields
    ml_keywords = StringProperty('')
    ai_keywords = StringProperty('')
    cs_keywords = StringProperty('')
    neuro_keywords = StringProperty('')
    bci_keywords = StringProperty('')

    # Weights
    weight_relevance = NumericProperty(0.60)
    weight_citation = NumericProperty(0.30)
    weight_recency = NumericProperty(0.10)

    # Other
    top_n = NumericProperty(5)
    semantic_scholar_key = StringProperty('')
    pubmed_key = StringProperty('')

    def on_enter(self):
        self._load_settings()

    def _get_settings_path(self) -> str:
        from kivy.app import App
        app = App.get_running_app()
        if app and hasattr(app, 'data_dir'):
            return os.path.join(app.data_dir, 'settings.json')
        return os.path.join(os.path.expanduser('~'), '.researchradar', 'settings.json')

    def _load_settings(self):
        path = self._get_settings_path()
        settings = dict(_DEFAULT_SETTINGS)

        if os.path.exists(path):
            try:
                with open(path, 'r', encoding='utf-8') as f:
                    saved = json.load(f)
                settings.update(saved)
            except (json.JSONDecodeError, OSError):
                logger.warning('Could not load settings — using defaults')

        interests = settings.get('interests', {})
        self.ml_keywords = interests.get('ml', '')
        self.ai_keywords = interests.get('ai', '')
        self.cs_keywords = interests.get('cs', '')
        self.neuro_keywords = interests.get('neuroscience', '')
        self.bci_keywords = interests.get('bci', '')

        self.weight_relevance = settings.get('weight_relevance', 0.60)
        self.weight_citation = settings.get('weight_citation', 0.30)
        self.weight_recency = settings.get('weight_recency', 0.10)
        self.top_n = settings.get('top_n', 5)
        self.semantic_scholar_key = settings.get('semantic_scholar_key', '')
        self.pubmed_key = settings.get('pubmed_key', '')

    def save_settings(self):
        """Validate and persist settings to JSON."""
        # Normalise weights to sum to 1.0
        total = self.weight_relevance + self.weight_citation + self.weight_recency
        if total > 0:
            self.weight_relevance /= total
            self.weight_citation /= total
            self.weight_recency /= total

        settings = {
            'interests': {
                'ml': self.ml_keywords,
                'ai': self.ai_keywords,
                'cs': self.cs_keywords,
                'neuroscience': self.neuro_keywords,
                'bci': self.bci_keywords,
            },
            'weight_relevance': round(self.weight_relevance, 2),
            'weight_citation': round(self.weight_citation, 2),
            'weight_recency': round(self.weight_recency, 2),
            'top_n': int(self.top_n),
            'semantic_scholar_key': self.semantic_scholar_key,
            'pubmed_key': self.pubmed_key,
        }

        path = self._get_settings_path()
        os.makedirs(os.path.dirname(path), exist_ok=True)

        try:
            with open(path, 'w', encoding='utf-8') as f:
                json.dump(settings, f, indent=2)
            logger.info('Settings saved to %s', path)
        except OSError:
            logger.error('Failed to save settings', exc_info=True)

        # Apply to running app
        from kivy.app import App
        app = App.get_running_app()
        if app and hasattr(app, 'apply_settings'):
            app.apply_settings(settings)