fit4ruby 3.5.0 → 3.9.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/fit4ruby.gemspec +2 -2
- data/lib/fit4ruby/Activity.rb +94 -55
- data/lib/fit4ruby/BDFieldNameTranslator.rb +36 -0
- data/lib/fit4ruby/DeviceInfo.rb +37 -0
- data/lib/fit4ruby/FDR_DevField_Extension.rb +81 -0
- data/lib/fit4ruby/FieldDescription.rb +26 -8
- data/lib/fit4ruby/FileId.rb +2 -1
- data/lib/fit4ruby/FitDataRecord.rb +85 -32
- data/lib/fit4ruby/FitDefinition.rb +11 -4
- data/lib/fit4ruby/FitDefinitionField.rb +6 -6
- data/lib/fit4ruby/FitDefinitionFieldBase.rb +15 -6
- data/lib/fit4ruby/FitDeveloperDataFieldDefinition.rb +1 -1
- data/lib/fit4ruby/FitFile.rb +2 -0
- data/lib/fit4ruby/FitMessageRecord.rb +26 -21
- data/lib/fit4ruby/FitRecord.rb +2 -1
- data/lib/fit4ruby/FitTypeDefs.rb +2 -2
- data/lib/fit4ruby/GlobalFitDictionaries.rb +366 -23
- data/lib/fit4ruby/GlobalFitMessage.rb +84 -14
- data/lib/fit4ruby/GlobalFitMessages.rb +83 -3
- data/lib/fit4ruby/Lap.rb +10 -1
- data/lib/fit4ruby/Record.rb +11 -2
- data/lib/fit4ruby/version.rb +1 -1
- data/spec/FitFile_spec.rb +198 -100
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f0a74c755c07cbbcfd9b17b9efeb16a62696fd9076c9ece178e00e51b3ce075
|
4
|
+
data.tar.gz: 81ee48cea068828a6ad08c5f4f274270ec96179159e585ecc9068eccbf1be3a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f140497b1f269075e912da5988238db3a279ef5baf20e4ce29f3b960307c3b87a4ada116283f17f5965a7e0e25e9b3e5bcdce7306b14ae49cb16d837692b239
|
7
|
+
data.tar.gz: 829a3ff7cee37f26218915d8370a0dd44fe6c24152c634f073fb0d25a543c3e50783188fe81f6d5cbbb00af42974eba1aed51f59ee25a108718773b7a65f8ad8
|
data/Gemfile.lock
CHANGED
data/fit4ruby.gemspec
CHANGED
@@ -24,9 +24,9 @@ EOT
|
|
24
24
|
spec.require_paths = ["lib"]
|
25
25
|
spec.required_ruby_version = '>=2.0'
|
26
26
|
|
27
|
-
spec.add_dependency('bindata', '
|
27
|
+
spec.add_dependency('bindata', '~>2.4.8')
|
28
28
|
spec.add_development_dependency('yard', '~>0.9.20')
|
29
|
-
spec.add_development_dependency('rake', '~>0.
|
29
|
+
spec.add_development_dependency('rake', '~>13.0.3')
|
30
30
|
spec.add_development_dependency('bundler', '>=1.6.4')
|
31
31
|
spec.add_development_dependency('rspec', '>=3.8')
|
32
32
|
spec.add_development_dependency('pry', '>=0.12')
|
data/lib/fit4ruby/Activity.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# = Activity.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
5
|
#
|
6
|
-
# Copyright (c) 2014, 2015 by Chris Schlaeger <cs@taskjuggler.org>
|
6
|
+
# Copyright (c) 2014, 2015, 2020 by Chris Schlaeger <cs@taskjuggler.org>
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of version 2 of the GNU General Public License as
|
@@ -33,45 +33,65 @@ require 'fit4ruby/PersonalRecords'
|
|
33
33
|
|
34
34
|
module Fit4Ruby
|
35
35
|
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
36
|
+
# Activity files are arguably the most common type of FIT file. The Activity
|
37
|
+
# class represents the top-level structure of an activity FIT file.
|
38
|
+
# It holds references to all other data structures. Each of the objects it
|
39
|
+
# references are direct equivalents of the message record structures used in
|
40
|
+
# the FIT file.
|
39
41
|
class Activity < FitDataRecord
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
# These symbols are a complete list of all the sub-sections that an
|
44
|
+
# activity FIT file may contain. This list is used to generate accessors,
|
45
|
+
# instance variables and other sections of code. Some are just simple
|
46
|
+
# instance variables, but the majority can appear multiple times and hence
|
47
|
+
# are stored in an Array.
|
48
|
+
FILE_SECTIONS = [
|
49
|
+
:file_id,
|
50
|
+
:file_creator,
|
51
|
+
:events,
|
52
|
+
:device_infos,
|
53
|
+
:data_sources,
|
54
|
+
:epo_data,
|
55
|
+
:user_profiles,
|
56
|
+
:user_data,
|
57
|
+
:sensor_settings,
|
58
|
+
:developer_data_ids,
|
59
|
+
:field_descriptions,
|
60
|
+
:records,
|
61
|
+
:hrv,
|
62
|
+
:laps,
|
63
|
+
:lengths,
|
64
|
+
:heart_rate_zones,
|
65
|
+
:physiological_metrics,
|
66
|
+
:sessions,
|
67
|
+
:personal_records
|
68
|
+
]
|
69
|
+
|
70
|
+
attr_accessor *FILE_SECTIONS
|
46
71
|
|
47
72
|
# Create a new Activity object.
|
48
73
|
# @param field_values [Hash] A Hash that provides initial values for
|
49
74
|
# certain fields of the FitDataRecord.
|
50
75
|
def initialize(field_values = {})
|
51
76
|
super('activity')
|
52
|
-
@meta_field_units['total_gps_distance'] = 'm'
|
53
|
-
@num_sessions = 0
|
54
77
|
|
55
|
-
|
56
|
-
|
57
|
-
|
78
|
+
# The variables hold references to other parts of the FIT file. These
|
79
|
+
# can either be direct references to a certain FIT file section or an
|
80
|
+
# Array in case the section can appear multiple times in the FIT file.
|
81
|
+
@file_id = new_file_id()
|
82
|
+
@file_creator = new_file_creator()
|
58
83
|
@epo_data = nil
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
@events = []
|
67
|
-
@sessions = []
|
68
|
-
@laps = []
|
69
|
-
@lengths = []
|
70
|
-
@records = []
|
71
|
-
@hrv = []
|
72
|
-
@heart_rate_zones = []
|
73
|
-
@personal_records = []
|
84
|
+
# Initialize the remaining variables as empty Array.
|
85
|
+
FILE_SECTIONS.each do |fs|
|
86
|
+
ivar_name = '@' + fs.to_s
|
87
|
+
unless instance_variable_defined?(ivar_name)
|
88
|
+
instance_variable_set(ivar_name, [])
|
89
|
+
end
|
90
|
+
end
|
74
91
|
|
92
|
+
# The following variables hold derived or auxilliary information that
|
93
|
+
# are not directly part of the FIT file.
|
94
|
+
@meta_field_units['total_gps_distance'] = 'm'
|
75
95
|
@cur_session_laps = []
|
76
96
|
|
77
97
|
@cur_lap_records = []
|
@@ -99,11 +119,6 @@ module Fit4Ruby
|
|
99
119
|
end
|
100
120
|
@device_infos.each.with_index { |d, index| d.check(index) }
|
101
121
|
@sensor_settings.each.with_index { |s, index| s.check(index) }
|
102
|
-
unless @num_sessions == @sessions.count
|
103
|
-
Log.fatal "Activity record requires #{@num_sessions}, but "
|
104
|
-
"#{@sessions.length} session records were found in the "
|
105
|
-
"FIT file."
|
106
|
-
end
|
107
122
|
|
108
123
|
# Records must have consecutively growing timestamps and distances.
|
109
124
|
ts = Time.parse('1989-12-31')
|
@@ -308,13 +323,17 @@ module Fit4Ruby
|
|
308
323
|
def write(io, id_mapper)
|
309
324
|
@file_id.write(io, id_mapper)
|
310
325
|
@file_creator.write(io, id_mapper)
|
326
|
+
@epo_data.write(io, id_mapper) if @epo_data
|
311
327
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
328
|
+
ary_ivars = []
|
329
|
+
FILE_SECTIONS.each do |fs|
|
330
|
+
ivar_name = '@' + fs.to_s
|
331
|
+
if (ivar = instance_variable_get(ivar_name)) && ivar.respond_to?(:sort)
|
332
|
+
ary_ivars += ivar
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
ary_ivars.sort.each do |s|
|
318
337
|
s.write(io, id_mapper)
|
319
338
|
end
|
320
339
|
super
|
@@ -464,18 +483,17 @@ module Fit4Ruby
|
|
464
483
|
# @return [TrueClass/FalseClass] true if both Activities are equal,
|
465
484
|
# otherwise false.
|
466
485
|
def ==(a)
|
467
|
-
super(a)
|
468
|
-
|
469
|
-
|
470
|
-
@
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
@sessions == a.sessions && personal_records == a.personal_records
|
486
|
+
return false unless super(a)
|
487
|
+
|
488
|
+
FILE_SECTIONS.each do |fs|
|
489
|
+
ivar_name = '@' + fs.to_s
|
490
|
+
ivar = instance_variable_get(ivar_name)
|
491
|
+
a_ivar = a.instance_variable_get(ivar_name)
|
492
|
+
|
493
|
+
return false unless ivar == a_ivar
|
494
|
+
end
|
495
|
+
|
496
|
+
true
|
479
497
|
end
|
480
498
|
|
481
499
|
# Create a new FitDataRecord.
|
@@ -521,7 +539,6 @@ module Fit4Ruby
|
|
521
539
|
# Ensure that all previous records have been assigned to a lap.
|
522
540
|
record = create_new_lap(lap_field_values)
|
523
541
|
end
|
524
|
-
@num_sessions += 1
|
525
542
|
@sessions << (record = Session.new(@cur_session_laps, @lap_counter,
|
526
543
|
field_values))
|
527
544
|
@cur_session_laps = []
|
@@ -530,7 +547,7 @@ module Fit4Ruby
|
|
530
547
|
when 'length'
|
531
548
|
record = create_new_length(field_values)
|
532
549
|
when 'record'
|
533
|
-
record = Record.new(field_values)
|
550
|
+
record = Record.new(self, field_values)
|
534
551
|
@cur_lap_records << record
|
535
552
|
@cur_length_records << record
|
536
553
|
@records << record
|
@@ -547,10 +564,31 @@ module Fit4Ruby
|
|
547
564
|
record
|
548
565
|
end
|
549
566
|
|
567
|
+
def export
|
568
|
+
# Collect all records in a consistent order.
|
569
|
+
records = []
|
570
|
+
FILE_SECTIONS.each do |fs|
|
571
|
+
ivar_name = '@' + fs.to_s
|
572
|
+
ivar = instance_variable_get(ivar_name)
|
573
|
+
|
574
|
+
next unless ivar
|
575
|
+
|
576
|
+
if ivar.respond_to?(:sort) and ivar.respond_to?(:empty?)
|
577
|
+
records += ivar.sort unless ivar.empty?
|
578
|
+
else
|
579
|
+
records << ivar if ivar
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
583
|
+
records.map do |record|
|
584
|
+
record.export
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
550
588
|
private
|
551
589
|
|
552
590
|
def create_new_lap(field_values)
|
553
|
-
lap = Lap.new(@cur_lap_records, @laps.last,
|
591
|
+
lap = Lap.new(self, @cur_lap_records, @laps.last,
|
554
592
|
field_values,
|
555
593
|
@length_counter, @cur_lap_lengths)
|
556
594
|
lap.message_index = @lap_counter - 1
|
@@ -573,6 +611,7 @@ module Fit4Ruby
|
|
573
611
|
|
574
612
|
length
|
575
613
|
end
|
614
|
+
|
576
615
|
end
|
577
616
|
|
578
617
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = FitDataRecord.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
|
+
#
|
6
|
+
# Copyright (c) 2020 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
13
|
+
module Fit4Ruby
|
14
|
+
|
15
|
+
# Some FIT message field names conflict with BinData reserved names. We use
|
16
|
+
# this translation method to map the conflicting names to BinData compatible
|
17
|
+
# names.
|
18
|
+
module BDFieldNameTranslator
|
19
|
+
|
20
|
+
BD_DICT = {
|
21
|
+
'array' => '_array',
|
22
|
+
'type' => '_type'
|
23
|
+
}
|
24
|
+
|
25
|
+
def to_bd_field_name(name)
|
26
|
+
if (bd_name = BD_DICT[name])
|
27
|
+
return bd_name
|
28
|
+
end
|
29
|
+
|
30
|
+
name
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
data/lib/fit4ruby/DeviceInfo.rb
CHANGED
@@ -32,6 +32,43 @@ module Fit4Ruby
|
|
32
32
|
@timestamp <=> fdr.timestamp
|
33
33
|
end
|
34
34
|
|
35
|
+
def numeric_manufacturer
|
36
|
+
if @manufacturer && @manufacturer.is_a?(String)
|
37
|
+
if @manufacturer[0..17] == 'Undocumented value'
|
38
|
+
return @manufacturer[18..-1].to_i
|
39
|
+
else
|
40
|
+
return GlobalFitDictionaries['manufacturer'].
|
41
|
+
value_by_name(@manufacturer)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Log.fatal "Unexpected @manufacturer (#{@manufacturer}) value"
|
46
|
+
end
|
47
|
+
|
48
|
+
def numeric_product
|
49
|
+
# The numeric product ID must be an integer or nil. In case the
|
50
|
+
# dictionary did not contain an entry for the numeric ID in the fit file
|
51
|
+
# the @garmin_product or @product variables contain a String starting
|
52
|
+
# with 'Undocumented value ' followed by the ID.
|
53
|
+
if @garmin_product && @garmin_product.is_a?(String)
|
54
|
+
if @garmin_product[0..17] == 'Undocumented value'
|
55
|
+
return @garmin_product[18..-1].to_i
|
56
|
+
else
|
57
|
+
return GlobalFitDictionaries['garmin_product'].
|
58
|
+
value_by_name(@garmin_product)
|
59
|
+
end
|
60
|
+
elsif @product && @product.is_a?(String)
|
61
|
+
if @product[0..17] == 'Undocumented value'
|
62
|
+
return @product[18..-1].to_i
|
63
|
+
else
|
64
|
+
return GlobalFitDictionaries['product'].value_by_name(@product)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
Log.fatal "Unexpected @product (#{@product}) or " +
|
69
|
+
"@garmin_product (#{@garmin_product}) values"
|
70
|
+
end
|
71
|
+
|
35
72
|
def check(index)
|
36
73
|
unless @device_index
|
37
74
|
Log.fatal 'device info record must have a device_index'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
# encoding: UTF-8
|
3
|
+
#
|
4
|
+
# = FDR_DevField_Extension.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
|
+
#
|
6
|
+
# Copyright (c) 2020 by Chris Schlaeger <cs@taskjuggler.org>
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of version 2 of the GNU General Public License as
|
10
|
+
# published by the Free Software Foundation.
|
11
|
+
#
|
12
|
+
|
13
|
+
module Fit4Ruby
|
14
|
+
|
15
|
+
# This module extends FitDataRecord derived classes in case they have
|
16
|
+
# developer fields.
|
17
|
+
module FDR_DevField_Extension
|
18
|
+
|
19
|
+
def create_dev_field_instance_variables
|
20
|
+
# Create instance variables for developer fields
|
21
|
+
@dev_field_descriptions = {}
|
22
|
+
@top_level_record.field_descriptions.each do |field_description|
|
23
|
+
# Only create instance variables if the FieldDescription is for this
|
24
|
+
# message number.
|
25
|
+
if field_description.native_mesg_num == @message.number
|
26
|
+
name = field_description.full_field_name(@top_level_record.
|
27
|
+
developer_data_ids)
|
28
|
+
create_instance_variable(name)
|
29
|
+
@dev_field_descriptions[name] = field_description
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def each_developer_field
|
35
|
+
@top_level_record.field_descriptions.each do |field_description|
|
36
|
+
# Only create instance variables if the FieldDescription is for this
|
37
|
+
# message number.
|
38
|
+
if field_description.native_mesg_num == @message.number
|
39
|
+
name = field_description.full_field_name(@top_level_record.
|
40
|
+
developer_data_ids)
|
41
|
+
yield(field_description, instance_variable_get('@' + name))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_unit_by_name(name)
|
47
|
+
if /[A-Za-z_]+_[A-F0-9]{16}/ =~ name
|
48
|
+
@dev_field_descriptions[name].units
|
49
|
+
else
|
50
|
+
super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def export
|
55
|
+
message = super
|
56
|
+
|
57
|
+
each_developer_field do |field_description, ivar|
|
58
|
+
field = field_description.message.fields_by_number[
|
59
|
+
field_description.native_field_num]
|
60
|
+
fit_value = field.native_to_fit(ivar)
|
61
|
+
unless field.is_undefined?(fit_value)
|
62
|
+
fld = {
|
63
|
+
'number' => field_description.native_field_num | 128,
|
64
|
+
'value' => field.fit_to_native(fit_value),
|
65
|
+
#'human' => field.to_human(fit_value),
|
66
|
+
'type' => field.type
|
67
|
+
}
|
68
|
+
fld['unit'] = field.opts[:unit] if field.opts[:unit]
|
69
|
+
fld['scale'] = field.opts[:scale] if field.opts[:scale]
|
70
|
+
|
71
|
+
message['fields'][field.name] = fld
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
message
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# = FieldDescription.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
5
|
#
|
6
|
-
# Copyright (c) 2017, 2018, 2019 by Chris Schlaeger <cs@taskjuggler.org>
|
6
|
+
# Copyright (c) 2017, 2018, 2019, 2020 by Chris Schlaeger <cs@taskjuggler.org>
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of version 2 of the GNU General Public License as
|
@@ -25,6 +25,24 @@ module Fit4Ruby
|
|
25
25
|
def initialize(field_values = {})
|
26
26
|
super('field_description')
|
27
27
|
set_field_values(field_values)
|
28
|
+
|
29
|
+
@full_field_name = nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def full_field_name(developer_data_ids)
|
33
|
+
return @full_field_name if @full_field_name
|
34
|
+
|
35
|
+
if @developer_data_index >=
|
36
|
+
developer_data_ids.size
|
37
|
+
Log.error "Developer data index #{@developer_data_index} is too large"
|
38
|
+
return
|
39
|
+
end
|
40
|
+
|
41
|
+
app_id = developer_data_ids[@developer_data_index].application_id
|
42
|
+
# Convert the byte array with the app ID into a 16 character hex string.
|
43
|
+
app_id_str = app_id.map { |i| '%02X' % i }.join('')
|
44
|
+
@full_field_name =
|
45
|
+
"#{@field_name.gsub(/[^A-Za-z0-9_]/, '_')}_#{app_id_str}"
|
28
46
|
end
|
29
47
|
|
30
48
|
def create_global_definition(fit_entity)
|
@@ -35,18 +53,18 @@ module Fit4Ruby
|
|
35
53
|
return
|
36
54
|
end
|
37
55
|
|
38
|
-
if @developer_data_index >=
|
39
|
-
fit_entity.top_level_record.developer_data_ids.size
|
40
|
-
Log.error "Developer data index #{@developer_data_index} is too large"
|
41
|
-
return
|
42
|
-
end
|
43
|
-
|
44
56
|
msg = messages[@native_mesg_num] ||
|
45
57
|
messages.message(@native_mesg_num, gfm.name)
|
46
58
|
unless (@fit_base_type_id & 0x7F) < FIT_TYPE_DEFS.size
|
47
59
|
Log.error "fit_base_type_id #{@fit_base_type_id} is too large"
|
48
60
|
return
|
49
61
|
end
|
62
|
+
|
63
|
+
# A fit file may include multiple definitions of the same field. We
|
64
|
+
# ignore all subsequent definitions.
|
65
|
+
return if msg.has_field?(full_field_name(fit_entity.top_level_record.
|
66
|
+
developer_data_ids))
|
67
|
+
|
50
68
|
options = {}
|
51
69
|
options[:scale] = @scale if @scale
|
52
70
|
options[:offset] = @offset if @offset
|
@@ -54,7 +72,7 @@ module Fit4Ruby
|
|
54
72
|
options[:unit] = @units
|
55
73
|
msg.field(@field_definition_number,
|
56
74
|
FIT_TYPE_DEFS[@fit_base_type_id & 0x7F][1],
|
57
|
-
|
75
|
+
@full_field_name, options)
|
58
76
|
end
|
59
77
|
|
60
78
|
end
|
data/lib/fit4ruby/FileId.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
#
|
4
4
|
# = FileId.rb -- Fit4Ruby - FIT file processing library for Ruby
|
5
5
|
#
|
6
|
-
# Copyright (c) 2014 by Chris Schlaeger <cs@taskjuggler.org>
|
6
|
+
# Copyright (c) 2014, 2020 by Chris Schlaeger <cs@taskjuggler.org>
|
7
7
|
#
|
8
8
|
# This program is free software; you can redistribute it and/or modify
|
9
9
|
# it under the terms of version 2 of the GNU General Public License as
|
@@ -23,6 +23,7 @@ module Fit4Ruby
|
|
23
23
|
@time_created = Time.at(Time.now.to_i)
|
24
24
|
@manufacturer = 'development'
|
25
25
|
@type = 'activity'
|
26
|
+
@product = 0
|
26
27
|
|
27
28
|
set_field_values(field_values)
|
28
29
|
end
|