<commit_before>import gobject
import json
from collections import defaultdict
from itertools import chain
from functools import partial
from sc_utils import reify, smart_dict
from delegates.base import SystemCalcDelegate


class BatteryConfiguration(object):
	""" Holds custom mapping information about a service that corresponds to a
	    battery. """
	def __init__(self, parent, number, service, name, enabled):
		self.parent = parent
		self.number = number
		self.service = str(service)
		self.name = None if name is None else str(name)
		self.enabled = bool(enabled)

		self.service_item = self.parent._settings.addSetting(
			"/Settings/SystemSetup/Batteries/Configuration/{}/Service".format(number),
			"", 0, 0, callback=partial(self.on_setting_change, "service", str))
		self.name_item = self.parent._settings.addSetting(
			"/Settings/SystemSetup/Batteries/Configuration/{}/Name".format(number),
			"", 0, 0, callback=partial(self.on_setting_change, "name", str))
		self.enabled_item = self.parent._settings.addSetting(
			"/Settings/SystemSetup/Batteries/Configuration/{}/Enabled".format(number),
			0, 0, 1, callback=partial(self.on_setting_change, "enabled", bool))
		self.service_item.set_value(service)

	def on_setting_change(self, key, cast, service, path, value):
		setattr(self, key, cast(value['Value']))
		self.parent.changed = True


class BatteryTracker(object):
	_paths = (
		'/Dc/0/Voltage',
		'/Dc/0/Current',
		'/Dc/0/Power',
		'/Dc/0/Temperature',
		'/Soc',
		'/TimeToGo')

	def __init__(self, service, instance, monitor):
		self.service = service
		self.instance = instance
		self.monitor = monitor
		self.channel = None
		self._tracked = { k: None for k in self._paths }

	@property
	def valid(self):
		# It is valid if it has at least a voltage
		return self.monitor.get_value(self.service, '/Dc/0/Voltage') is not None

	@property
	def name(self):
		return self.monitor.get_value(self.service, '/CustomName') or self.monitor.get_value(self.service, '/ProductName')

	@reify
	def service_id(self):
		""" Generate an identifier that uniquely identifies the type
			of service and the instance. """
		return "{}/{}".format('.'.join(self.service.split('.')[:3]), self.instance)

	def update(self):
		changed = False
		for k, v in self._tracked.iteritems():
			n = self.monitor.get_value(self.service, k)
			if n != v:
				self._tracked[k] = n
				changed = True
		return changed

	def _data(self):
		power = self._tracked['/Dc/0/Power']
		voltage = self._tracked['/Dc/0/Voltage']
		current = self._tracked['/Dc/0/Current']
		calculated_power = voltage * current if None not in (voltage, current) else None
		return {
			'id': self.service,
			'instance': self.instance,
			'voltage': voltage,
			'current': current,
			'power': power or calculated_power,
			'temperature': self._tracked['/Dc/0/Temperature'],
			'soc': self._tracked['/Soc'],
			'timetogo': self._tracked.get('/TimeToGo', None),
			'name': self.name,
			'state': None if power is None else (1 if power > 30 else (2 if power < 30 else 0))
		}<commit_msg>batterydata: Fix incorrect state calculation for battery charge/discharge state.<commit_after>import gobject
import json
from collections import defaultdict
from itertools import chain
from functools import partial
from sc_utils import reify, smart_dict
from delegates.base import SystemCalcDelegate


class BatteryConfiguration(object):
	""" Holds custom mapping information about a service that corresponds to a
	    battery. """
	def __init__(self, parent, number, service, name, enabled):
		self.parent = parent
		self.number = number
		self.service = str(service)
		self.name = None if name is None else str(name)
		self.enabled = bool(enabled)

		self.service_item = self.parent._settings.addSetting(
			"/Settings/SystemSetup/Batteries/Configuration/{}/Service".format(number),
			"", 0, 0, callback=partial(self.on_setting_change, "service", str))
		self.name_item = self.parent._settings.addSetting(
			"/Settings/SystemSetup/Batteries/Configuration/{}/Name".format(number),
			"", 0, 0, callback=partial(self.on_setting_change, "name", str))
		self.enabled_item = self.parent._settings.addSetting(
			"/Settings/SystemSetup/Batteries/Configuration/{}/Enabled".format(number),
			0, 0, 1, callback=partial(self.on_setting_change, "enabled", bool))
		self.service_item.set_value(service)

	def on_setting_change(self, key, cast, service, path, value):
		setattr(self, key, cast(value['Value']))
		self.parent.changed = True


class BatteryTracker(object):
	_paths = (
		'/Dc/0/Voltage',
		'/Dc/0/Current',
		'/Dc/0/Power',
		'/Dc/0/Temperature',
		'/Soc',
		'/TimeToGo')

	def __init__(self, service, instance, monitor):
		self.service = service
		self.instance = instance
		self.monitor = monitor
		self.channel = None
		self._tracked = { k: None for k in self._paths }

	@property
	def valid(self):
		# It is valid if it has at least a voltage
		return self.monitor.get_value(self.service, '/Dc/0/Voltage') is not None

	@property
	def name(self):
		return self.monitor.get_value(self.service, '/CustomName') or self.monitor.get_value(self.service, '/ProductName')

	@reify
	def service_id(self):
		""" Generate an identifier that uniquely identifies the type
			of service and the instance. """
		return "{}/{}".format('.'.join(self.service.split('.')[:3]), self.instance)

	def update(self):
		changed = False
		for k, v in self._tracked.iteritems():
			n = self.monitor.get_value(self.service, k)
			if n != v:
				self._tracked[k] = n
				changed = True
		return changed

	def _data(self):
		power = self._tracked['/Dc/0/Power']
		voltage = self._tracked['/Dc/0/Voltage']
		current = self._tracked['/Dc/0/Current']
		calculated_power = voltage * current if None not in (voltage, current) else None
		return {
			'id': self.service,
			'instance': self.instance,
			'voltage': voltage,
			'current': current,
			'power': power or calculated_power,
			'temperature': self._tracked['/Dc/0/Temperature'],
			'soc': self._tracked['/Soc'],
			'timetogo': self._tracked.get('/TimeToGo', None),
			'name': self.name,
			'state': None if power is None else (1 if power > 30 else (2 if power < -30 else 0))
		}
{'fraction_non_alphanumeric': 0.14025974025974025, 'fraction_numerical': 0.007792207792207792, 'mean_word_length': 4.247870528109029, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1517342', 'n_tokens_mistral': 2221, 'n_tokens_neox': 1982, 'n_words': 520}