<commit_before># This file is part of NIT ( http://www.nitlanguage.org ).
#
# Copyright 2014-2015 <NAME> <<EMAIL>>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Statistics about the Game.
#
# This module uses `GameReactor` to extract statistics about the game from
# triggered `Github::Event`.
module statistics

import game
import github::hooks
import counter

redef class GameEntity

	# Statistics manager for this entity.
	fun stats: GameStatsManager is abstract
end

redef class Game

	redef var stats is lazy do return new GameStatsManager(game, self)

	redef fun save do
		super
		stats.save_in(self.key)
	end

	redef fun pretty do
		var res = new FlatBuffer
		res.append super
		res.append "# stats:\n"
		res.append stats.pretty
		return res.write_to_string
	end
end

redef class Player

	redef var stats is lazy do return new GameStatsManager(game, self)

	redef fun save do
		super
		stats.save_in(self.key)
	end

	redef fun nitcoins do return stats["nitcoins"]
	redef fun nitcoins=(nc) do stats["nitcoins"] = nc

	redef fun pretty do
		var res = new FlatBuffer
		res.append super
		res.append "# stats:\n"
		res.append stats.pretty
		return res.write_to_string
	end
end

# Store game stats for defined period.
class GameStatsManager
	super GameEntity
	super Counter[String]

	redef var game

	# The GameEntity monitored by these statistics.
	var owner: GameEntity


	# Returns the `GameStats` instance for the overall statistics.
	var overall: GameStats is lazy do
		return load_stats_for("all")
	end

	# Returns the `GameStats` instance for the current year statistics.
	var yearly: GameStats is lazy do
		var date = new Tm.gmtime
		var key = date.strftime("%Y")
		return load_stats_for(key)
	end

	# Returns the `GameStats` instance for the current month statistics.
	var monthly: GameStats is lazy do
		var date = new Tm.gmtime
		var key = date.strftime("%Y-%m")
		return load_stats_for(key)
	end

	# Returns the `GameStats` instance for the current day statistics.
	var daily: GameStats is lazy do
		var date = new Tm.gmtime
		var key = date.strftime("%Y-%m-%d")
		return load_stats_for(key)
	end

	# Returns the `GameStats` instance for the current week statistics.
	var weekly: GameStats is lazy do
		var date = new Tm.gmtime
		var key = date.strftime("%Y-W%U")
		return load_stats_for(key)
	end

	# Load statistics for a `period` key.
	fun load_stats_for(period: String): GameStats do
		var key = owner.key / self.key / period
		if not game.store.has_key(key) then
			return new GameStats(game, period, owner)
		end
		var json = game.store.load_object(key)
		return new GameStats.from_json(game, period, owner, json)
	end

	redef fun [](key) do return overall[key]

	redef fun []=(key, value) do
		overall[key] = value
		yearly[key] = value
		monthly[key] = value
		daily[key] = value
		weekly[key] = value
	end

	redef fun inc(e) do
		overall.inc(e)
		yearly.inc(e)
		monthly.inc(e)
		daily.inc(e)
		weekly.inc(e)
	end

	redef fun dec(e) do
		overall.dec(e)
		yearly.dec(e)
		monthly.dec(e)
		daily.dec(e)
		weekly.dec(e)
	end

	redef fun save_in(key) do
		overall.save_in(key / self.key)
		yearly.save_in(key / self.key)
		monthly.save_in(key / self.key)
		daily.save_in(key / self.key)
		weekly.save_in(key / self.key)
	end

	redef fun pretty do return overall.pretty
end

# Game statistics structure that can be saved as a `GameEntity`.
class GameStats
	super GameEntity
	super Counter[String]

	redef var game

	# The pedriod these stats are about.
	var period: String


	# Load `self` from saved data.
	init from_json(game: Game, period: String, json: JsonObject) do
		for k, v in json do self[k] = v.as(Int)
	end

	redef fun to_json do
		var obj = new JsonObject
		for k, v in self do obj[k] = v
		return obj
	end

	redef fun pretty do
		var res = new FlatBuffer
		for k, v in self do
			res.append "# {v} {k}\n"
		end
		return res.write_to_string
	end
end

# `GameReactor` that computes statistics about the game.
class StatisticsReactor
	super GameReactor

	redef fun react_event(game, e) do e.react_stats_event(game)
end

redef class GithubEvent
	# Reacts to a statistics related event.
	#
	# Called by `StatisticsReactor::react_event`.
	# No-op by default.
	private fun react_stats_event(game: Game) do end<commit_msg>nitrpg: better organization for stats objects<commit_after># This file is part of NIT ( http://www.nitlanguage.org ).
#
# Copyright 2014-2015 <NAME> <<EMAIL>>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Statistics about the Game.
#
# This module uses `GameReactor` to extract statistics about the game from
# triggered `Github::Event`.
module statistics

import game
import github::hooks
import counter

redef class GameEntity

	# Statistics manager for this entity.
	fun stats: GameStatsManager is abstract
end

redef class Game

	redef var stats is lazy do return new GameStatsManager(game, self)

	redef fun save do
		super
		stats.save_in(self.key)
	end

	redef fun pretty do
		var res = new FlatBuffer
		res.append super
		res.append "# stats:\n"
		res.append stats.pretty
		return res.write_to_string
	end
end

redef class Player

	redef var stats is lazy do return new GameStatsManager(game, self)

	redef fun save do
		super
		stats.save_in(self.key)
	end

	redef fun nitcoins do return stats["nitcoins"]
	redef fun nitcoins=(nc) do stats["nitcoins"] = nc

	redef fun pretty do
		var res = new FlatBuffer
		res.append super
		res.append "# stats:\n"
		res.append stats.pretty
		return res.write_to_string
	end
end

# Store game stats for defined period.
class GameStatsManager
	super GameEntity
	super Counter[String]

	redef var game

	# The GameEntity monitored by these statistics.
	var owner: GameEntity

	# Current date to extract stats
	private var date = new Tm.gmtime

	# Returns the `GameStats` instance for the overall statistics.
	var overall: GameStats = load_stats_for("all") is lazy

	# Returns the `GameStats` instance for the current year statistics.
	var yearly: GameStats = load_stats_for(date.strftime("%Y")) is lazy

	# Returns the `GameStats` instance for the current month statistics.
	var monthly: GameStats = load_stats_for(date.strftime("%Y-%m")) is lazy

	# Returns the `GameStats` instance for the current day statistics.
	var daily: GameStats = load_stats_for(date.strftime("%Y-%m-%d")) is lazy

	# Returns the `GameStats` instance for the current week statistics.
	var weekly: GameStats = load_stats_for(date.strftime("%Y-W%U")) is lazy

	# Load statistics for a `period` key.
	fun load_stats_for(period: String): GameStats do
		var key = owner.key / self.key / period
		if not game.store.has_key(key) then
			return new GameStats(game, period, owner)
		end
		var json = game.store.load_object(key)
		return new GameStats.from_json(game, period, owner, json)
	end

	redef fun [](key) do return overall[key]

	redef fun []=(key, value) do
		overall[key] = value
		yearly[key] = value
		monthly[key] = value
		daily[key] = value
		weekly[key] = value
	end

	redef fun inc(e) do
		overall.inc(e)
		yearly.inc(e)
		monthly.inc(e)
		daily.inc(e)
		weekly.inc(e)
	end

	redef fun dec(e) do
		overall.dec(e)
		yearly.dec(e)
		monthly.dec(e)
		daily.dec(e)
		weekly.dec(e)
	end

	redef fun save_in(key) do
		overall.save_in(key / self.key)
		yearly.save_in(key / self.key)
		monthly.save_in(key / self.key)
		daily.save_in(key / self.key)
		weekly.save_in(key / self.key)
	end

	redef fun pretty do return overall.pretty
end

# Game statistics structure that can be saved as a `GameEntity`.
class GameStats
	super GameEntity
	super Counter[String]

	redef var game

	# The period these stats are about.
	var period: String

	# The game entity these stats are about.
	var owner: GameEntity

	redef var key = "{owner.key}-{period}" is lazy

	# Load `self` from saved data.
	init from_json(game: Game, period: String, owner: GameEntity, json: JsonObject) do
		var values = json.get_or_null("values")
		if not values isa JsonObject then return
		for k, v in values do self[k] = v.as(Int)
	end

	redef fun to_json do
		var obj = super
		obj["period"] = period
		obj["owner"] = owner.key
		var values = new JsonObject
		values.recover_with(self)
		obj["values"] = values
		return obj
	end

	redef fun pretty do
		var res = new FlatBuffer
		for k, v in self do
			res.append "# {v} {k}\n"
		end
		return res.write_to_string
	end
end

# `GameReactor` that computes statistics about the game.
class StatisticsReactor
	super GameReactor

	redef fun react_event(game, e) do e.react_stats_event(game)
end

redef class GithubEvent
	# Reacts to a statistics related event.
	#
	# Called by `StatisticsReactor::react_event`.
	# No-op by default.
	private fun react_stats_event(game: Game) do end
{'fraction_non_alphanumeric': 0.08621403436141585, 'fraction_numerical': 0.002483957772717864, 'mean_word_length': 3.855778894472362, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, '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': '6794216', 'n_tokens_mistral': 3400, 'n_tokens_neox': 3146, 'n_words': 1177}