musical_score 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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