musical_score 0.1.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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +25 -0
  3. data/.gitignore +11 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +1156 -0
  6. data/.travis.yml +7 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +21 -0
  10. data/README.md +45 -0
  11. data/Rakefile +6 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/codeclimate-config.patch +1191 -0
  15. data/lib/musical_score/attribute/attribute.rb +69 -0
  16. data/lib/musical_score/attribute/clef.rb +44 -0
  17. data/lib/musical_score/attribute/key.rb +74 -0
  18. data/lib/musical_score/attribute/time.rb +43 -0
  19. data/lib/musical_score/const.rb +16 -0
  20. data/lib/musical_score/element_base.rb +17 -0
  21. data/lib/musical_score/errors.rb +3 -0
  22. data/lib/musical_score/io/importer.rb +22 -0
  23. data/lib/musical_score/location.rb +13 -0
  24. data/lib/musical_score/measures.rb +42 -0
  25. data/lib/musical_score/note/lyric.rb +43 -0
  26. data/lib/musical_score/note/notation/notation.rb +105 -0
  27. data/lib/musical_score/note/notation/tie.rb +22 -0
  28. data/lib/musical_score/note/notation/tuplet.rb +22 -0
  29. data/lib/musical_score/note/note.rb +141 -0
  30. data/lib/musical_score/note/pitch.rb +140 -0
  31. data/lib/musical_score/note/time_modification.rb +33 -0
  32. data/lib/musical_score/note/type.rb +29 -0
  33. data/lib/musical_score/notes.rb +37 -0
  34. data/lib/musical_score/part/measure.rb +49 -0
  35. data/lib/musical_score/part/part.rb +45 -0
  36. data/lib/musical_score/score/identification/creator.rb +29 -0
  37. data/lib/musical_score/score/identification/encoding.rb +66 -0
  38. data/lib/musical_score/score/identification/identification.rb +47 -0
  39. data/lib/musical_score/score/part/part.rb +37 -0
  40. data/lib/musical_score/score/score.rb +126 -0
  41. data/lib/musical_score/version.rb +4 -0
  42. data/lib/musical_score.rb +12 -0
  43. data/musical_score.gemspec +42 -0
  44. metadata +184 -0
@@ -0,0 +1,141 @@
1
+ require 'contracts'
2
+ Dir[File.expand_path('../', __FILE__) << '/**/*.rb'].each do |file|
3
+ # require file except myself
4
+ if(file != __FILE__)
5
+ require file
6
+ end
7
+ end
8
+ module MusicalScore
9
+ module Note
10
+ class Note < MusicalScore::ElementBase
11
+ attr_accessor :lyric, :location
12
+ attr_reader :duration, :tie, :dot, :time_modification, :actual_duration, :pitch, :rest, :type, :notation
13
+ include Contracts
14
+
15
+ # constructor for rest note
16
+ Contract KeywordArgs[
17
+ :duration => Pos,
18
+ :tie => Maybe[Enum[*TYPE_START_STOP]],
19
+ :dot => Optional[Nat],
20
+ :lyric => Optional[nil],
21
+ :pitch => Optional[nil],
22
+ :rest => true,
23
+ :type => MusicalScore::Note::Type,
24
+ :time_modification => Maybe[MusicalScore::Note::TimeModification],
25
+ :notation => Maybe[MusicalScore::Note::Notation::Notation],
26
+ ] => Any
27
+ def initialize(
28
+ duration:,
29
+ tie: nil,
30
+ dot: 0,
31
+ lyric: nil,
32
+ pitch: nil,
33
+ rest: true,
34
+ type:,
35
+ time_modification: nil,
36
+ notation: nil,
37
+ **rest_args
38
+ )
39
+ @duration = duration
40
+ @tie = tie
41
+ @dot = dot
42
+ @lyric = lyric
43
+ @pitch = pitch
44
+ @rest = rest
45
+ @type = type
46
+ @time_modification = time_modification
47
+ @notation = notation
48
+
49
+ set_actual_duration
50
+ end
51
+
52
+ # constructor for pitch note
53
+ Contract KeywordArgs[
54
+ :duration => Pos,
55
+ :tie => Maybe[Enum[*TYPE_START_STOP]],
56
+ :dot => Optional[Nat],
57
+ :lyric => Maybe[MusicalScore::Note::Lyric],
58
+ :pitch => MusicalScore::Note::Pitch,
59
+ :rest => Optional[false],
60
+ :type => MusicalScore::Note::Type,
61
+ :time_modification => Maybe[MusicalScore::Note::TimeModification],
62
+ :notation => Maybe[MusicalScore::Note::Notation::Notation],
63
+ ] => Any
64
+ def initialize(
65
+ duration:,
66
+ tie: nil,
67
+ dot: 0,
68
+ lyric: nil,
69
+ pitch:,
70
+ rest: false,
71
+ type:,
72
+ time_modification: nil,
73
+ notation: nil,
74
+ **rest_args
75
+ )
76
+ @duration = duration
77
+ @tie = tie
78
+ @dot = dot
79
+ @lyric = lyric
80
+ @pitch = pitch
81
+ @rest = rest
82
+ @type = type
83
+ @time_modification = time_modification
84
+ @notation = notation
85
+
86
+ set_actual_duration
87
+ end
88
+
89
+ Contract REXML::Element => MusicalScore::Note::Note
90
+ def self.create_by_xml(xml_doc)
91
+ dots = 0
92
+ xml_doc.elements.each("dot") do |elemet|
93
+ dots += 1
94
+ end
95
+ duration = xml_doc.elements["duration"].text.to_i
96
+ type = MusicalScore::Note::Type.new(xml_doc.elements["type"].text)
97
+
98
+ tie = xml_doc.elements["tie"] ? xml_doc.elements["tie"].attributes["type"].to_sym : nil
99
+
100
+ notation_doc = xml_doc.elements["notations"]
101
+ notation = notation_doc ? MusicalScore::Note::Notation::Notation.create_by_xml(notation_doc) : nil
102
+
103
+ time_modification_doc = xml_doc.elements["time-modification"]
104
+ time_modification = time_modification_doc ? MusicalScore::Note::TimeModification.create_by_xml(time_modification_doc) : nil
105
+ rest = xml_doc.elements["rest"] ? true : false
106
+ if (rest)
107
+ return MusicalScore::Note::Note.new(duration: duration, tie: tie, dot: dots, rest: rest, type: type, time_modification: time_modification, notation: notation)
108
+ else
109
+ pitch = MusicalScore::Note::Pitch.create_by_xml(xml_doc.elements["pitch"])
110
+ lyric_doc = xml_doc.elements["lyric"]
111
+ lyric = lyric_doc ? MusicalScore::Note::Lyric.create_by_xml(lyric_doc) : nil
112
+ return MusicalScore::Note::Note.new(duration: duration, tie: tie, dot: dots, type: type, lyric: lyric, pitch: pitch, time_modification: time_modification, notation: notation)
113
+ end
114
+ end
115
+
116
+ def export_xml
117
+ note_element = REXML::Element.new('note')
118
+ note_element.add_element('rest') if @rest
119
+ note_element.add_element(@pitch.export_xml) if @pitch
120
+ note_element.add_element('duration').add_text(@duration.to_s)
121
+ note_element.add_element('tie').add_attribute('type', @tie.to_s) if @tie
122
+ note_element.add_element(@type.export_xml)
123
+ note_element.add_element(@time_modification.export_xml) if @time_modification
124
+ note_element.add_element(@lyric.export_xml(1)) if @lyric
125
+ note_element.add_element(@notation.export_xml) if @notation
126
+
127
+ return note_element
128
+ end
129
+
130
+ private
131
+ def set_actual_duration
132
+ unless(@time_modification)
133
+ @actual_duration = Rational(@duration, 1)
134
+ else
135
+ total_duration = @duration * @time_modification.normal_notes
136
+ @actual_duration = Rational(total_duration, @time_modification.actual_notes)
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,140 @@
1
+ require 'contracts'
2
+ module MusicalScore
3
+ module Note
4
+ class Pitch < MusicalScore::ElementBase
5
+ include Comparable
6
+ include Contracts
7
+ # pitch names
8
+ @@key = {
9
+ :C => 0,
10
+ :D => 2,
11
+ :E => 4,
12
+ :F => 5,
13
+ :G => 7,
14
+ :A => 9,
15
+ :B => 11
16
+ }
17
+ attr_accessor :step, :alter, :octave
18
+
19
+ # constructor
20
+ #
21
+ # @example create Pitch object
22
+ # MusicalScore::Note::Pitch.new(:C, 0, 3) # => C3
23
+ #
24
+ # @param step The key of the pitch described as "C", "D", "E", etc.
25
+ # @param alter The number of sharp (positive number) or flat (negative number).
26
+ # @param octave The octave number
27
+ #
28
+ Contract Enum[*@@key.keys], Enum[*AVAILABLE_NUMBERS_OF_ALTER], Nat => Any
29
+ def initialize(step, alter = 0, octave = 0)
30
+ @step = step.to_sym
31
+ @alter = alter
32
+ @octave = octave
33
+ end
34
+
35
+ # Pitch is comparable
36
+ #
37
+ # @example
38
+ # a = MusicalScore::Note::Pitch.new(:C, 0, 3)
39
+ # b = MusicalScore::Note::Pitch.new(:D, 0 ,3)
40
+ # a < b # => true
41
+ def <=> (other)
42
+ self.note_number <=> other.note_number
43
+ end
44
+
45
+ # Given a note_number like MIDI note_number, return the Pitch object with positive number of alter
46
+ #
47
+ # @example
48
+ # a = MusicalScore::Note::Pitch.new_note_sharp(70)
49
+ # a # => [:step => :A, :alter => 1, :octave => 5 ]
50
+ Contract Nat => MusicalScore::Note::Pitch
51
+ def self.new_note_sharp(note_number)
52
+ step_key_num = note_number % NUMBER_OF_NOTES
53
+ octave = note_number / NUMBER_OF_NOTES
54
+ # calculate step and alter
55
+ candidate_keys = @@key.keys.select{ |item| step_key_num >= @@key[item] }
56
+ key = candidate_keys.max_by{ |item| @@key[item] }
57
+
58
+ return MusicalScore::Note::Pitch.new(key, step_key_num-@@key[key], octave)
59
+ end
60
+
61
+ # Given a note_number like MIDI note_number, return the Pitch object with negative number of alter
62
+ #
63
+ # @example
64
+ # a = MusicalScore::Note::Pitch.new_note_sharp(70)
65
+ # a # => [:step => :B, :alter => -1, :octave => 5 ]
66
+ #
67
+ Contract Nat => MusicalScore::Note::Pitch
68
+ def self.new_note_flat(note_number)
69
+ step_key_num = note_number % NUMBER_OF_NOTES
70
+ octave = note_number / NUMBER_OF_NOTES
71
+ # calculate step and alter
72
+ candidate_keys = @@key.keys.select{ |item| step_key_num <= @@key[item] }
73
+ key = candidate_keys.min_by{ |item| @@key[item] }
74
+
75
+ return MusicalScore::Note::Pitch.new(key, step_key_num-@@key[key], octave)
76
+ end
77
+
78
+ def note_number
79
+ result = (NUMBER_OF_NOTES * octave) + @@key[step] + alter
80
+ return result
81
+ end
82
+
83
+ # Given argument true, return note string like "D##"
84
+ #
85
+ Contract Maybe[Bool] => String
86
+ def to_s(is_note_str = false)
87
+ if is_note_str
88
+ result = "%s%s%d" % [@step.to_s, alter_to_s, @octave]
89
+ return result
90
+ else
91
+ return self.to_s
92
+ end
93
+ end
94
+
95
+ Contract REXML::Element => MusicalScore::Note::Pitch
96
+ def self.create_by_xml(xml_doc)
97
+ step = xml_doc.elements["step"].text.to_sym
98
+ octave = xml_doc.elements["octave"].text.to_i
99
+ alter = xml_doc.elements["alter"] ? xml_doc.elements["alter"].text.to_i : 0
100
+ return MusicalScore::Note::Pitch.new(step, alter, octave)
101
+ end
102
+
103
+ def export_xml
104
+ pitch_element = REXML::Element.new('pitch')
105
+ step_element = REXML::Element.new('step').add_text(@step.to_s)
106
+ octave_element = REXML::Element.new('octave').add_text(@octave.to_s)
107
+
108
+ pitch_element.add_element(step_element)
109
+ if (@alter != 0)
110
+ alter_element = REXML::Element.new('alter').add_text(@alter.to_s)
111
+ pitch_element.add_element(alter_element)
112
+ end
113
+ pitch_element.add_element(octave_element)
114
+
115
+ return pitch_element
116
+ end
117
+
118
+ private
119
+
120
+ def alter_to_s
121
+ num = @alter.abs
122
+ if (num == 0)
123
+ return ""
124
+ elsif (@alter < 0)
125
+ result = ''
126
+ num.times do |i|
127
+ result += 'b'
128
+ end
129
+ return result
130
+ else
131
+ result = ''
132
+ num.times do |i|
133
+ result += '#'
134
+ end
135
+ return result
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,33 @@
1
+ require 'contracts'
2
+ module MusicalScore
3
+ module Note
4
+ class TimeModification < MusicalScore::ElementBase
5
+ include Contracts
6
+ attr_reader :actual_notes, :normal_notes
7
+
8
+ Contract Pos, Pos => Any
9
+ def initialize(actual_notes, normal_notes)
10
+ @actual_notes = actual_notes
11
+ @normal_notes = normal_notes
12
+ end
13
+
14
+ Contract REXML::Element => MusicalScore::Note::TimeModification
15
+ def self.create_by_xml(xml_doc)
16
+ actual_notes = xml_doc.elements["actual-notes"].text.to_i
17
+ normal_notes = xml_doc.elements["normal-notes"].text.to_i
18
+ return MusicalScore::Note::TimeModification.new(actual_notes, normal_notes)
19
+ end
20
+
21
+ def export_xml
22
+ time_modification_element = REXML::Element.new('time-modification')
23
+ actual_notes_element = REXML::Element.new('actual-notes').add_text(@actual_notes.to_s)
24
+ normal_notes_element = REXML::Element.new('normal-notes').add_text(@normal_notes.to_s)
25
+
26
+ time_modification_element.add_element(actual_notes_element)
27
+ time_modification_element.add_element(normal_notes_element)
28
+
29
+ return time_modification_element
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ module MusicalScore
3
+ module Note
4
+ class Type < MusicalScore::ElementBase
5
+ include Contracts
6
+
7
+ @@size = %w(
8
+ 128th
9
+ 64th
10
+ 32nd
11
+ 16th
12
+ eighth
13
+ quarter
14
+ half
15
+ whole
16
+ breve
17
+ )
18
+ attr_reader :size
19
+ Contract Enum[*@@size] => Any
20
+ def initialize(size)
21
+ @size = size
22
+ end
23
+
24
+ def export_xml
25
+ return REXML::Element.new('type').add_text(@size.to_s)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ require 'contracts'
2
+ require 'musical_score/note/note'
3
+ module MusicalScore
4
+ class Notes < MusicalScore::ElementBase
5
+ include Contracts
6
+ include Enumerable
7
+ attr_reader :notes, :duration
8
+
9
+ Contract ArrayOf[MusicalScore::Note::Note] => Any
10
+ def initialize(notes)
11
+ @notes = notes
12
+ end
13
+ def divide_to_notes_and_rests
14
+ divided_array = @notes.partition { |note| note.rest }
15
+ return { note: divided_array[1], rest: divided_array[0] }
16
+ end
17
+
18
+ def [](index)
19
+ return @notes[index]
20
+ end
21
+
22
+ def each
23
+ @notes.each do |note|
24
+ yield note
25
+ end
26
+ end
27
+
28
+ def set_location(location, number)
29
+ current_location = MusicalScore::Location.new(number, location)
30
+ @notes.each do |note|
31
+ note.location = current_location
32
+ current_location = MusicalScore::Location.new(number, current_location.location + note.actual_duration)
33
+ end
34
+ @duration = current_location.location - location
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,49 @@
1
+ require 'contracts'
2
+ require 'musical_score/attribute/attribute'
3
+ require 'musical_score/notes'
4
+
5
+ module MusicalScore
6
+ module Part
7
+ class Measure < MusicalScore::ElementBase
8
+ include Contracts
9
+ attr_reader :attribute, :number, :notes
10
+ attr_accessor :length
11
+ Contract MusicalScore::Notes, Nat, Maybe[MusicalScore::Attribute::Attribute]=> Any
12
+ def initialize(notes, number, attribute = nil)
13
+ @notes = notes
14
+ @number = number
15
+ @attribute = attribute
16
+ end
17
+
18
+ Contract REXML::Element => MusicalScore::Part::Measure
19
+ def self.create_by_xml(xml_doc)
20
+ attribute_doc = xml_doc.elements["//attributes"]
21
+ attributes = attribute_doc ? MusicalScore::Attribute::Attribute.create_by_xml(attribute_doc) : nil
22
+ number = xml_doc.attributes["number"].to_i
23
+ note_array = Array.new
24
+ xml_doc.elements.each("//note") do |element|
25
+ note = MusicalScore::Note::Note.create_by_xml(element)
26
+ note_array.push(note)
27
+ end
28
+ notes = MusicalScore::Notes.new(note_array)
29
+ return MusicalScore::Part::Measure.new(notes, number, attributes)
30
+ end
31
+
32
+ def export_xml
33
+ measure_element = REXML::Element.new('measure')
34
+ measure_element.add_attribute('number',@number.to_s)
35
+ measure_element.add_element(@attribute.export_xml) if @attribute
36
+
37
+ @notes.each do |note|
38
+ measure_element.add_element(note.export_xml)
39
+ end
40
+
41
+ return measure_element
42
+ end
43
+
44
+ def location
45
+ return @notes[0].location
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,45 @@
1
+ require 'contracts'
2
+ Dir[File.expand_path('../', __FILE__) << '/**/*.rb'].each do |file|
3
+ # require file except myself
4
+ if(file != __FILE__)
5
+ require file
6
+ end
7
+ end
8
+ module MusicalScore
9
+ module Part
10
+ class Part < MusicalScore::ElementBase
11
+ include Contracts
12
+ attr_accessor :measures
13
+ Contract MusicalScore::Measures => Any
14
+ def initialize(measures)
15
+ @measures = measures
16
+ end
17
+
18
+ Contract REXML::Element => MusicalScore::Part::Part
19
+ def self.create_by_xml(xml_doc)
20
+ measure_array = Array.new
21
+ xml_doc.elements.each("//measure") do |element|
22
+ measure = MusicalScore::Part::Measure.create_by_xml(element)
23
+ measure_array.push(measure)
24
+ end
25
+ measures = MusicalScore::Measures.new(measure_array)
26
+ return MusicalScore::Part::Part.new(measures)
27
+ end
28
+
29
+ def export_xml(number)
30
+ part = REXML::Element.new('part')
31
+ part.add_attribute('id', "P" + number.to_s)
32
+
33
+ @measures.each do |measure|
34
+ part.add_element(measure.export_xml)
35
+ end
36
+
37
+ return part
38
+ end
39
+
40
+ def set_location
41
+ @measures.set_location
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ require 'contracts'
2
+ module MusicalScore
3
+ module Score
4
+ module Identification
5
+ class Creator < MusicalScore::ElementBase
6
+ attr_reader :name, :type
7
+ include Contracts
8
+ Contract String, Enum[*TYPE_CREATOR] => Any
9
+ def initialize(name, type)
10
+ @name = name
11
+ @type = type
12
+ end
13
+
14
+ Contract REXML::Element => MusicalScore::Score::Identification::Creator
15
+ def self.create_by_xml(xml_doc)
16
+ type = xml_doc.attributes["type"].to_sym
17
+ name = xml_doc.text
18
+ return MusicalScore::Score::Identification::Creator.new(name, type)
19
+ end
20
+ def export_xml
21
+ creator = REXML::Element.new('creator')
22
+ creator.add_attribute('type', @type)
23
+ creator.add_text(@name)
24
+ return creator
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,66 @@
1
+ require 'contracts'
2
+ require 'time'
3
+
4
+ module MusicalScore
5
+ module Score
6
+ module Identification
7
+ class Encoding < MusicalScore::ElementBase
8
+ include Contracts
9
+ attr_reader :encoding_date, :encoding_description, :softwares, :supports
10
+ Contract Time, String, ArrayOf[String], ArrayOf[String] => Any
11
+ def initialize(encoding_date, encoding_description, softwares, supports)
12
+ @encoding_date = encoding_date
13
+ @encoding_description = encoding_description
14
+ @softwares = softwares
15
+ @supports = supports
16
+ end
17
+
18
+ Contract REXML::Element => MusicalScore::Score::Identification::Encoding
19
+ def self.create_by_xml(xml_doc)
20
+
21
+ encoding_date = Time.new
22
+ if (xml_doc.elements["//encoding-date"])
23
+ encoding_date = Time.parse(xml_doc.elements["//encoding-date"].text)
24
+ end
25
+ encoding_description = xml_doc.elements["//encoding-description"] ? xml_doc.elements["//encoding_description"].text : ''
26
+ softwares = Array.new
27
+ xml_doc.elements.each("//software") do |element|
28
+ softwares.push(element.text)
29
+ end
30
+ supports = Array.new
31
+ xml_doc.elements.each("//supports") do |element|
32
+ if (element.attributes["type"] == "yes")
33
+ supports.push(element.attributes["element"])
34
+ end
35
+ end
36
+ return MusicalScore::Score::Identification::Encoding.new(encoding_date, encoding_description, softwares, supports)
37
+ end
38
+
39
+ def export_xml
40
+ encoding = REXML::Element.new('encoding')
41
+ @softwares.each do |software|
42
+ software_e = REXML::Element.new('software')
43
+ software_e.add_text(software)
44
+ encoding.add_element(software_e)
45
+ end
46
+ encoding_date = REXML::Element.new('encoding-date')
47
+ encoding_date.add_text(@encoding_date.strftime("%Y-%m-%d"))
48
+ encoding.add_element(encoding_date)
49
+ @supports.each do |support|
50
+ supports_e = REXML::Element.new('supports')
51
+ supports_e.add_attribute('type','yes')
52
+ supports_e.add_attribute('element',support)
53
+ encoding.add_element(supports_e)
54
+ end
55
+ desc_e = REXML::Element.new('encoding-description')
56
+ if (@encoding_description != '')
57
+ desc_e.add_text(@encoding_description)
58
+ encoding.add_element(desc_e)
59
+ end
60
+
61
+ return encoding
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,47 @@
1
+ require 'contracts'
2
+ Dir[File.expand_path('../', __FILE__) << '/**/*.rb'].each do |file|
3
+ # require file except myself
4
+ if(file != __FILE__)
5
+ require file
6
+ end
7
+ end
8
+ module MusicalScore
9
+ module Score
10
+ module Identification
11
+ class Identification < MusicalScore::ElementBase
12
+ include Contracts
13
+ attr_reader :creators, :encoding
14
+ Contract ArrayOf[Maybe[MusicalScore::Score::Identification::Creator]], Maybe[MusicalScore::Score::Identification::Encoding] => Any
15
+ def initialize(creators, encodings)
16
+ @creators = creators
17
+ @encoding = encodings
18
+ end
19
+
20
+ Contract REXML::Element => MusicalScore::Score::Identification::Identification
21
+ def self.create_by_xml(xml_doc)
22
+ creator_doc = xml_doc.elements["//creator"]
23
+ encoding_doc = xml_doc.elements["//encoding"]
24
+
25
+ creators = Array.new
26
+ xml_doc.elements.each("//creator") do |element|
27
+ creators.push(MusicalScore::Score::Identification::Creator.create_by_xml(element))
28
+ end
29
+
30
+ encoding = encoding_doc ? MusicalScore::Score::Identification::Encoding.create_by_xml(encoding_doc) : nil
31
+
32
+ return MusicalScore::Score::Identification::Identification.new(creators, encoding)
33
+ end
34
+
35
+ def export_xml
36
+ identification = REXML::Element.new('identification')
37
+ @creators.each do |creator|
38
+ identification.add_element(creator.export_xml)
39
+ end
40
+ identification.add_element(@encoding.export_xml)
41
+
42
+ return identification
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,37 @@
1
+ require 'contracts'
2
+ Dir[File.expand_path('../', __FILE__) << '/**/*.rb'].each do |file|
3
+ # require file except myself
4
+ if(file != __FILE__)
5
+ require file
6
+ end
7
+ end
8
+ module MusicalScore
9
+ module Score
10
+ module Part
11
+ class Part < MusicalScore::ElementBase
12
+ include Contracts
13
+ attr_reader :part_name, :part_abbreviation
14
+
15
+ Contract String, String => Any
16
+ def initialize(part_name, part_abbreviation)
17
+ @part_name = part_name
18
+ @part_abbreviation = part_abbreviation
19
+ end
20
+
21
+ def export_xml(index)
22
+ score_part_element = REXML::Element.new('score-part')
23
+ score_part_element.add_attribute('id', "P" + index.to_s)
24
+
25
+ part_name_element = REXML::Element.new('part-name')
26
+ part_name_element.add_text(@part_name)
27
+ part_abbreviation_element = REXML::Element.new('part-abbreviation')
28
+ part_abbreviation_element.add_text(@part_abbreviation)
29
+ score_part_element.add_element(part_name_element)
30
+ score_part_element.add_element(part_abbreviation_element)
31
+
32
+ return score_part_element
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end