orientdb-time-graph 0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ ---
2
+ :active_orient:
3
+ ## Namespace: Prefix of Model-Objects. :self -> ActiveOrient::Model::{name}
4
+ ## :object => No Prefix
5
+ ## :active_orient => ActiveOrient::{name}
6
+ :namespace: :object
7
+ :model_dir: 'model'
8
+
@@ -0,0 +1,21 @@
1
+ ---
2
+ :orientdb:
3
+ :production:
4
+ :server: 172.28.50.25 # localhost
5
+ :user: hctw
6
+ :password: a***k
7
+ :database: o
8
+ :test:
9
+ :server: 10.222.148.109
10
+ :user: hctw
11
+ :password: s*p**
12
+ :database: test
13
+ :development:
14
+ :server: 10.222.148.109
15
+ :user: hctw
16
+ :password: s*p**
17
+ :database: demo
18
+ :port: 2480
19
+ :logger: stdout # 'file' or 'stdout'
20
+
21
+ # hfx: 101
@@ -0,0 +1,60 @@
1
+ module TG
2
+ module Setup
3
+ def self.init_database database_instance= V.db
4
+ stored_namespace = ActiveOrient::Model.namespace
5
+ ActiveOrient::Init.define_namespace { TG }
6
+ (logger= ActiveOrient::OrientDB.logger).progname= 'TG::Setup#InitDatabase'
7
+ # because edges are not resolved because of the namingconvention
8
+ tg_edges = [ :time_of, :day_of, :month_of, :grid_of ]
9
+ time_base_vertices = [ :stunde, :tag, :monat, :jahr ]
10
+ edges = V.db.class_hierarchy( base_class: 'E') & tg_edges.map( &:to_s )
11
+ vertices = V.db.class_hierarchy( base_class: 'tg_time_base' ) & time_base_vertices.map( &:to_s )
12
+ logger.info{ "affected-database-classes: \n #{ (vertices + edges).join(', ')}" }
13
+
14
+ delete_class = -> (c,d) do
15
+ the_class = ActiveOrient::Model.orientdb_class( name: c, superclass: d)
16
+ logger.info{ "The Class: "+the_class.to_s+ " removed from Database" }
17
+ the_class.delete_class
18
+ end
19
+ if defined?(TimeBase)
20
+ vertices.each{|v| delete_class[ v, :tg_time_base ] }
21
+ delete_class[ :tg_time_base, :V ]
22
+ end
23
+
24
+ logger.progname= 'TG::Setup#InitDatabase'
25
+ cleared_database = V.db.database_classes
26
+ logger.info{ " Creating Classes " }
27
+ V.create_class :time_base # --> TimeBase
28
+ # hour, day: month cannot be alloacated, because Day is a class of DateTime and thus is reserved
29
+ time_base_classes = TimeBase.create_class *time_base_vertices # --> Hour, Day, Month
30
+ TimeBase.create_property :value, type: :integer
31
+ #
32
+ ## this puts an index on child-classes
33
+ time_base_classes.each{|c| c.create_index c.ref_name+'_value_idx' , type: :notunique, on: :value }
34
+
35
+ # modified naming-convention in model/e.rb
36
+ edges = E.create_class *tg_edges # --> TIME_OF, :DAY_OF
37
+ edges.each &:uniq_index
38
+
39
+ # restore namespace
40
+ ActiveOrient::Init.define_namespace { stored_namespace }
41
+
42
+ V.db.database_classes - cleared_database # return_value
43
+ end
44
+ end
45
+ end
46
+ # to_do: define validations
47
+ # hour_class = r.create_vertex_class "Hour", properties: {value_string: {type: :string}, value: {type: :integer}}
48
+ # hour_class.alter_property property: "value", attribute: "MIN", alteration: 0
49
+ # hour_class.alter_property property: "value", attribute: "MAX", alteration: 23
50
+ #
51
+ # day_class = r.create_vertex_class "Day", properties: {value_string: {type: :string}, value: {type: :integer}}
52
+ # day_class.alter_property property: "value", attribute: "MIN", alteration: 1
53
+ # day_class.alter_property property: "value", attribute: "MAX", alteration: 31
54
+ #
55
+ # month_class = r.create_vertex_class "Month", properties: {value_string: {type: :string}, value: {type: :integer}}
56
+ # month_class.alter_property property: "value", attribute: "MIN", alteration: 1
57
+ # month_class.alter_property property: "value", attribute: "MAX", alteration: 12
58
+ #
59
+
60
+ # timeof_class = r.create_edge_class "TIMEOF"
@@ -0,0 +1,68 @@
1
+ require 'active-orient'
2
+ require_relative 'time_graph.rb'
3
+ require_relative 'support.rb'
4
+
5
+ require_relative 'init_db'
6
+
7
+
8
+
9
+ module TG
10
+
11
+ # completes the parameter for calling ActiveOrient::Init.connect
12
+ #
13
+ # Is called from connect only if ActiveOrient.default_server is not set previously
14
+ #
15
+ # otherwise the credentials from the main-activeorient-instance are used.
16
+ def self.set_defaults **login
17
+ c = { :server => 'localhost',
18
+ :port => 2480,
19
+ :protocol => 'http',
20
+ :user => 'root',
21
+ :password => 'root',
22
+ :database => 'temp'
23
+ }.merge login
24
+
25
+ ActiveOrient.default_server= { user: c[:user], password: c[:password] ,
26
+ server: c[:server], port: c[:port] }
27
+ ActiveOrient.database = c[:database]
28
+ end
29
+
30
+ def self.connect **login
31
+ project_root = File.expand_path('../..', __FILE__)
32
+ set_defaults( **login) unless ActiveOrient.default_server.is_a?(Hash) && ActiveOrient.default_server[:user].present?
33
+ ActiveOrient::Init.define_namespace { TG }
34
+ # a provided block is used to introduce additional locations of model-files
35
+ the_model_dirs = block_given? ? [ "#{project_root}/model", yield].flatten : [ "#{project_root}/model" ]
36
+ ActiveOrient::OrientDB.new preallocate: true, model_dir: the_model_dirs
37
+ @time_graph = TG.const_defined?(:TIME_OF) ? TG::TIME_OF.count > 0 : nil
38
+ end
39
+
40
+ def self.time_graph?
41
+ @time_graph
42
+ end
43
+ def self.check_and_initialize database_instance
44
+ if database_instance.get_classes( "name").values.flatten.include? 'time_base'
45
+ return true
46
+ else
47
+ TG::Setup.init_database database_instance
48
+ puts "Database-Structure allocated"
49
+ puts "Exiting now, please restart and call »TG::TimeGraph.populate«"
50
+ Kernel.exit
51
+ end
52
+ end
53
+
54
+ def self.info
55
+ puts "-------------- TIME GRAPH ------------------"
56
+ puts "Allocated Years : "
57
+ puts TG::Jahr.all.map(&:value).sort.join('; ')
58
+ puts ""
59
+ puts "Type: #{TG::Stunde.all.empty? ? "Date-Graph" : "DateTime-Graph"}"
60
+ puts ""
61
+
62
+ end
63
+ end
64
+
65
+
66
+
67
+
68
+
@@ -0,0 +1,40 @@
1
+ #require 'bunny'
2
+ require 'active_support'
3
+ require 'active-orient'
4
+ require 'yaml'
5
+ require_relative 'orientdb_time_graph'
6
+ #require 'dry/core/class_attributes'
7
+ #require_relative "logging"
8
+ require_relative "init_db"
9
+
10
+
11
+ module TG
12
+
13
+ ## Standalone setup
14
+ ##
15
+ ## initializes ActiveOrient and adds time-graph database-classes
16
+ ## through namespace
17
+ #
18
+ # valid environments: :test, :development, :production
19
+ def self.setup environment = :test
20
+
21
+ read_yml = -> (key) do
22
+ YAML::load_file( File.expand_path('../../config/connect.yml',__FILE__))[key]
23
+ end
24
+
25
+
26
+ logon = read_yml[:orientdb][environment]
27
+
28
+ ActiveOrient::Init.connect **logon
29
+ TG.connect **logon
30
+ # we have to initialise the timegraph at this point, otherwise any
31
+ # manual requirement fails.
32
+ unless ActiveOrient::Model.namespace.send :const_defined?, 'Tag'
33
+ Setup.init_database V.orientdb
34
+ end
35
+
36
+ end
37
+
38
+
39
+
40
+ end
@@ -0,0 +1,38 @@
1
+ ## We are defining to_tg methods for Strings, Date and DateTiem objects.
2
+ ## Strings are converted to the time format.
3
+ #
4
+ class Date
5
+ def to_tg
6
+ # old method performed queries
7
+ # Date.today.to_tg
8
+ # INFO->select from tg_jahr where value = 2019
9
+ # INFO->select expand (out_tg_month_of.in[value = 4]) from #117:0
10
+ # INFO->select expand (out_tg_day_of.in[value = 2]) from #108:6
11
+ #
12
+ # the alternative:
13
+ # TG::Jahr[year].monat(month).tag(day).orient_flatten
14
+ # which can be combined through
15
+ # query "select expand (out_tg_day_of.in[value = #{day}]) from (select expand (out_tg_month_of.in[value = #{month}]) from (select from tg_jahr where value = #{year} ) ) "
16
+ #
17
+ # this is realized in fetch
18
+ TG::Tag.fetch self
19
+ end
20
+ end
21
+
22
+ class DateTime
23
+ def to_tg
24
+ if TG.time_graph?
25
+ TG::Monat[month].tag(day).stunde(hour).pop.pop
26
+ else
27
+ TG::Tag.fetch self
28
+ end
29
+ end
30
+ end
31
+
32
+ class String
33
+ def to_tg
34
+ date = DateTime.parse(self)
35
+ date.to_tg
36
+ end
37
+ end
38
+
@@ -0,0 +1,100 @@
1
+ #require 'time'
2
+
3
+ module TG
4
+
5
+ class TimeGraph
6
+ class << self # singleton class
7
+ ## we populate the graph with a 1:n-Layer
8
+ # (year -->) n[month] --> n[day] ( --> n[hour] ])
9
+ # thus creating edges is providing a static :from-vertex to numerous :to-vertices
10
+ # the to:vertices are first created and fenced in an array. Then all edges are created at once.
11
+ # In Rest-Mode this is much quicker.
12
+ def populate years = (1900 .. 2050), delete: true
13
+
14
+ count_gridspace = -> do
15
+ [TG::Jahr,TG::Monat,TG::Tag,TG::Stunde].map{|x| "#{x.ref_name} -> #{x.count}" }
16
+ end
17
+
18
+ if delete
19
+ puts count_gridspace[].join('; ')
20
+ puts "deleting content"
21
+ [TG::Jahr,TG::Monat,TG::Tag,TG::Stunde].each{|x| x.delete all: true}
22
+ puts "checking .."
23
+ puts count_gridspace[].join('; ')
24
+ end
25
+
26
+ kind_of_grid = if years.is_a? Range
27
+ 'daily'
28
+ else
29
+ years = years.is_a?(Fixnum) ? [years]: years
30
+ 'hourly'
31
+ end
32
+
33
+ ### switch logger level
34
+ previous_looger_level = V.db.logger.level
35
+ V.db.logger.level = 2
36
+ ### NOW WHERE THE DATABASE IS CLEAN, POPULATE IT WITH A DAILY GRID
37
+ print "Grid: "
38
+ year_grid, month_grid, day_grid, hour_grid = nil
39
+ years.each do | the_year |
40
+ year_vertex = TG::Jahr.create value: the_year
41
+ # puts "YEAR_GRID: #{year_grid.inspect}"
42
+ TG::GRID_OF.create( from: year_grid , to: year_vertex ) if year_grid.present?
43
+ year_grid = year_vertex
44
+ month_vertices = ( 1 .. 12 ).map do | the_month |
45
+ month_vertex= TG::Monat.create value: the_month
46
+ TG::GRID_OF.create( from: month_grid , to: month_vertex ) if month_grid.present?
47
+ month_grid = month_vertex
48
+ last_month_day = (Date.new( the_year, the_month+1, 1)-1).day rescue 31 # rescue covers month > 12
49
+ day_vertices = ( 1 .. last_month_day ).map do | the_day |
50
+ day_vertex = TG::Tag.create value: the_day
51
+ TG::GRID_OF.create( from: day_grid , to: day_vertex ) if day_grid.present?
52
+ day_grid = day_vertex
53
+ if kind_of_grid == 'hourly'
54
+ hour_vertices = (0 .. 23).map do |h|
55
+ hour_vertex = Stunde.create( value: h)
56
+
57
+ TG::GRID_OF.create( from: hour_grid , to: hour_vertex ) if hour_grid.present?
58
+ hour_grid = hour_vertex
59
+ hour_vertex # return_value
60
+ end
61
+ TG::TIME_OF.create from: day_vertex, to: hour_vertices
62
+ end
63
+ day_vertex # return_value
64
+ end
65
+ TG::DAY_OF.create from: month_vertex, to: day_vertices
66
+ month_vertex # return_value
67
+ end
68
+ print "#{the_year} "
69
+ TG::MONTH_OF.create from: year_vertex, to: month_vertices
70
+ end
71
+ print "\n"
72
+ V.db.logger.level = previous_looger_level
73
+ end
74
+ end
75
+ end # class
76
+ end # Module
77
+ ## here we start if the file is called from the command-lind
78
+ if $0 == __FILE__
79
+ require './config/boot'
80
+ #TG::Setup.init_database # --> config/init_db
81
+ TG::TimeGraph.populate
82
+
83
+
84
+ print "\n" * 4
85
+ puts '-' * 40
86
+ puts "Features of the DateTime Graph"
87
+ puts '-' * 40
88
+ puts
89
+ puts "Allocated Month => Monat.first.value:\t\t" + Monat.first.value.to_s
90
+ puts
91
+ puts "Adressing Days => Monat.first.tag[2].value:\t" + Monat.first.tag[2].value.to_s
92
+ puts
93
+ puts "Display Date => Monat.first.tag[13].datum:\t"+ Monat.first.tag[13].datum.to_s
94
+
95
+ puts "Display next Date => Monat.first.tag[13].next.datum:\t"+ Monat.first.tag[13].next.datum.to_s
96
+
97
+
98
+
99
+
100
+ end
@@ -0,0 +1,7 @@
1
+
2
+ class E #< ActiveOrient::Model
3
+ def self.naming_convention name=nil
4
+ name.present? ? name.upcase : ref_name.upcase
5
+ end
6
+ end
7
+
@@ -0,0 +1,3 @@
1
+ class TG::DAY_OF
2
+
3
+ end
@@ -0,0 +1,3 @@
1
+ class TG::GRID_OF
2
+
3
+ end
@@ -0,0 +1,22 @@
1
+
2
+ class TG::Jahr #< TG::TimeBase
3
+ def der_monat m
4
+ m >0 && m<13 ? out_tg_month_of[m].in : nil
5
+ end
6
+
7
+ # returns an array of days
8
+ # thus enables the use as
9
+ # Monat[9].tag[9]
10
+ def monat *key
11
+ if key.blank?
12
+ out_tg_month_of.in
13
+ else
14
+ key= key.first if key.is_a?(Array) && key.size == 1
15
+ # out_tg_month_of[key].in
16
+ nodes( :out, via: /month/ , where: { value: key } )
17
+ end
18
+ end
19
+
20
+
21
+ end
22
+
@@ -0,0 +1,57 @@
1
+ class TG::Monat # < TG::TimeBase
2
+ # starts at a given month-entry
3
+ # tg_monat.in tg_month_of out --> tg_jahr
4
+ def _jahr
5
+ query.nodes :in, via: TG::MONTH_OF
6
+ end
7
+ def der_tag d
8
+ # d=d-1
9
+ d >0 && d<31 ? out_tg_day_of[d].in : nil
10
+ end
11
+
12
+ # returns an array of days
13
+ # thus enables the use as
14
+ # Monat[9].tag[9]
15
+ def tag *key
16
+ if key.blank?
17
+ out_tg_day_of.in
18
+ else
19
+ # out_tg_day_of.in
20
+ key= key.first if key.size == 1
21
+ nodes( :out, via: /day/ , where: { value: key } )
22
+ end
23
+ end
24
+
25
+ # returns the specified edge
26
+ # i.e. Monat[9]
27
+ #
28
+
29
+ def jahr
30
+ _jahr.execute.first
31
+ # in_tg_month_of.out.first
32
+ end
33
+
34
+ # returns the absolute Month-Value
35
+ #
36
+ # enables easy calculations betwwen month-vertices
37
+ #
38
+ # i.e. TG::Jahr[2013].monat(4).abs_value.first - TG::Jahr[2012].monat(9).abs_value.first
39
+ # => 7
40
+ def abs_value
41
+ jahr.value * 12 + value
42
+ end
43
+
44
+ def self.fetch datum , &b # parameter: a date
45
+ # query_database( "select expand (out_tg_day_of.in[value = #{datum.day}]) from (select expand (out_tg_month_of.in[value = #{datum.month}]) from (select from tg_jahr where value = #{datum.year} ) ) ") &.first
46
+ q = OrientSupport::OrientQuery.new from: TG::Jahr, where: { value: datum.year }
47
+ w = OrientSupport::OrientQuery.new from: q
48
+ w.nodes :out, via: TG::MONTH_OF, where: { value: datum.month }
49
+
50
+ query_database( w, &b).first
51
+ end
52
+
53
+ #TG::Monat.fetch Date.new(2000,4,5)
54
+ #21.06.(06:29:11) INFO->select expand ( outE('tg_month_of').in[ value = 4 ] ) from ( select from tg_jahr where value = 2000 )
55
+ # => #<TG::Monat:0x00000000032fbe28 @metadata={:type=>"d", :class=>"tg_monat", :version=>34, :fieldTypes=>"out_tg_day_of=g,in_tg_month_of=g,in_tg_grid_of=g,out_tg_grid_of=g", :cluster=>132, :record=>225, :edges=>{:in=>["tg_month_of", "tg_grid_of"], :out=>["tg_day_of", "tg_grid_of"]}}, @d=nil, @attributes={:out_tg_day_of=>["#158:6859", "#159:6859", "#160:6859", "#153:6860", "#154:6860", "#155:6860", "#156:6860", "#157:6860", "#158:6860", "#159:6860", "#160:6860", "#153:6861", "#154:6861", "#155:6861", "#156:6861", "#157:6861", "#158:6861", "#159:6861", "#160:6861", "#153:6862", "#154:6862", "#155:6862", "#156:6862", "#157:6862", "#158:6862", "#159:6862", "#160:6862", "#153:6863", "#154:6863", "#155:6863"], :in_tg_month_of=>["#164:225"], :value=>4, :in_tg_grid_of=>["#173:7103"], :out_tg_grid_of=>["#172:7107"]}>
56
+
57
+ end
File without changes
@@ -0,0 +1,16 @@
1
+ class TG::Stunde # < TG::TimeBase
2
+
3
+ def tag
4
+ in_tg_time_of.out
5
+ end
6
+
7
+ def datum
8
+ month = in_tg_time_of.out.in_tg_day_of.out.value
9
+ day = in_tg_time_of.out.value
10
+ "#{day.first}.#{month.flatten.first}.#{Date.today.year} #{value}:00"
11
+ end
12
+ def next
13
+ puts value.inspect
14
+ in_tg_day_of.out.first.tag( value + 1 )
15
+ end
16
+ end