stringyfi 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 796dc3f1361b70dbb6c86d6f7ef77639796d12e5
4
- data.tar.gz: f7ce1efbc6ead2e92c99b37f629540cc69d6f5db
2
+ SHA256:
3
+ metadata.gz: 2504e7e1f7968f25505c18c985b8fa910e65f2508505ae43c9df9f63e96ff8f2
4
+ data.tar.gz: f8ae2eb44c809c6510935bc0c51b7707da561b9012abad46b945e75282f815e8
5
5
  SHA512:
6
- metadata.gz: 92a250942f88d6ee07ff351ce5a4fd7a2998a675f8773b1782a913cc94fc5bde540a98fcdbf2bc40b0d5d6baba3a0f1c142c4708eb776d6c3dc666f067a68c7e
7
- data.tar.gz: 07ea32854390d1bcb07065ef3f5a44609399d56f1dbc04df387bd44044f66c5451ad9573c6965440b954653dfb353039f2889671a148cb744fc6a22d0f3485e4
6
+ metadata.gz: 0f1dca73381e9bfbce3004d2da120020855bab46b740745d81c07a4ae6addd1695be10ab84ca383ffff2758e57b8b413726f62b6c4eb738c71a9a334c8226827
7
+ data.tar.gz: 78d71c3f0424a5be29291753e546e7e06271ffb05af6d30fd832fc592e69e3ab81c422c6d07afb97f1a9f6c9dd7ac9a4f02c054eeedaed25eef8da0df320f1f2
@@ -0,0 +1,32 @@
1
+ name: Ruby Tests
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v3
18
+
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: 3.3
23
+ bundler-cache: true
24
+
25
+ - name: Install dependencies
26
+ run: bundle install
27
+
28
+ - name: Run tests
29
+ run: bundle exec rspec
30
+
31
+ - name: Run rubocop
32
+ run: bundle exec rubocop
data/.rubocop.yml ADDED
@@ -0,0 +1,53 @@
1
+ AllCops:
2
+ NewCops: disable
3
+ SuggestExtensions: false
4
+ TargetRubyVersion: 3.0
5
+
6
+ Layout/FirstArrayElementIndentation:
7
+ EnforcedStyle: consistent
8
+
9
+ Layout/FirstHashElementIndentation:
10
+ EnforcedStyle: consistent
11
+
12
+ Layout/LineLength:
13
+ Max: 125
14
+
15
+ Metrics/AbcSize:
16
+ Max: 46
17
+
18
+ Metrics/BlockLength:
19
+ Max: 150
20
+
21
+ Metrics/ClassLength:
22
+ Max: 150
23
+
24
+ Metrics/CyclomaticComplexity:
25
+ Max: 9
26
+
27
+ Metrics/MethodLength:
28
+ Max: 30
29
+
30
+ Metrics/ParameterLists:
31
+ MaxOptionalParameters: 4
32
+
33
+ Metrics/PerceivedComplexity:
34
+ Max: 9
35
+
36
+ Style/BlockComments:
37
+ Exclude:
38
+ - 'spec/spec_helper.rb'
39
+
40
+ Style/ClassAndModuleChildren:
41
+ EnforcedStyle: compact
42
+
43
+ Style/Documentation:
44
+ Exclude:
45
+ - 'spec/**/*'
46
+
47
+ Style/SoleNestedConditional:
48
+ Exclude:
49
+ - 'lib/stringyfi/converter.rb'
50
+
51
+ Style/StderrPuts:
52
+ Exclude:
53
+ - 'lib/stringyfi/converter.rb'
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.4.1
1
+ 3.3.3
data/Gemfile CHANGED
@@ -1,4 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
- # Specify your gem's dependencies in amuse.gemspec
5
+ # Specify gem dependencies in stringyfi.gemspec
4
6
  gemspec
7
+
8
+ # development dependencies
9
+ gem 'bundler', '>= 2.2.33'
10
+ gem 'guard-rspec'
11
+ gem 'guard-rubocop'
12
+ gem 'rake'
13
+ gem 'rspec'
14
+ gem 'rubocop', require: false
data/Guardfile CHANGED
@@ -1,18 +1,13 @@
1
- # A sample Guardfile
2
- # More info at https://github.com/guard/guard#readme
1
+ # frozen_string_literal: true
3
2
 
4
- # Note: The cmd option is now required due to the increasing number of ways
5
- # rspec may be run, below are examples of the most common uses.
6
- # * bundler: 'bundle exec rspec'
7
- # * bundler binstubs: 'bin/rspec'
8
- # * spring: 'bin/rsspec' (This will use spring if running and you have
9
- # installed the spring binstubs per the docs)
10
- # * zeus: 'zeus rspec' (requires the server to be started separetly)
11
- # * 'just' rspec: 'rspec'
3
+ # More info at https://github.com/guard/guard#readme
12
4
  guard :rspec, cmd: 'bundle exec rspec' do
13
5
  watch(%r{^spec/.+_spec\.rb$})
14
- watch(%r{^lib/stringyfi/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
15
- watch('spec/spec_helper.rb') { "spec" }
16
-
6
+ watch(%r{^lib/stringyfi/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { 'spec' }
17
8
  end
18
9
 
10
+ guard :rubocop, cli: ['--display-cop-names'] do
11
+ watch(/.+\.rb$/)
12
+ watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
13
+ end
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Convert MusicXML to PIC assembler for running on the Boldport Club Stringy.
4
4
 
5
- [![Build Status](https://travis-ci.org/tardate/stringyfi.svg?branch=master)](https://travis-ci.org/tardate/stringyfi)
5
+ [![Ruby Tests](https://github.com/tardate/stringyfi/actions/workflows/ruby-tests.yml/badge.svg)](https://github.com/tardate/stringyfi/actions/workflows/ruby-tests.yml)
6
6
 
7
7
  ## About the Stringy
8
8
 
@@ -36,11 +36,11 @@ Add this line to your application's Gemfile:
36
36
 
37
37
  And then execute:
38
38
 
39
- $ bundle
39
+ bundle
40
40
 
41
41
  Or install it yourself as:
42
42
 
43
- $ gem install stringyfi
43
+ gem install stringyfi
44
44
 
45
45
  ## Usage
46
46
 
@@ -49,7 +49,7 @@ and emits the assembler source on STDOUT (so it can be redirected as appropriate
49
49
 
50
50
  For example:
51
51
 
52
- $ stringyfi ./spec/fixtures/music_xml/chromatic.xml > ../CustomDemo.X/demo.tun
52
+ stringyfi ./spec/fixtures/music_xml/chromatic.xml > ../CustomDemo.X/demo.tun
53
53
 
54
54
  The
55
55
  [spec/fixtures](./spec/fixtures/music_xml)
data/Rakefile CHANGED
@@ -1,12 +1,13 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
7
9
 
8
- desc "Open an irb session preloaded with this library"
10
+ desc 'Open an irb session preloaded with this library'
9
11
  task :console do
10
- sh "irb -rubygems -I lib -r stringyfi.rb"
12
+ sh 'irb -rubygems -I lib -r stringyfi.rb'
11
13
  end
12
-
data/bin/stringyfi CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
5
 
4
6
  require 'stringyfi'
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
2
4
 
5
+ # Main controller for the conversion process
3
6
  class StringyFi::Converter
4
-
5
7
  INITIAL_OCTAVE = 1 # setup by the stringy firmware
6
8
  OCTAVE_OFFSET = 3 # how many octaves to offset the source
7
9
 
8
- attr_accessor :filename, :xml_doc
10
+ attr_accessor :filename
11
+ attr_writer :xml_doc
9
12
 
10
13
  def initialize(filename)
11
14
  self.filename = filename
@@ -21,40 +24,40 @@ class StringyFi::Converter
21
24
  puts score_body(shortest_fractional_duration)
22
25
  puts score_coda
23
26
 
24
- $stderr.puts ".. done."
27
+ $stderr.puts '.. done.'
25
28
  end
26
29
 
27
30
  def score_preamble
28
- <<-EOS
29
- ;**************************************************************************
30
- ;** Title: #{title}
31
- ;** Tempo: #{tempo}
32
- ;** Encoded: #{encoding_date} with #{encoding_software}
33
- ;** Stringyfied: #{Time.now}
34
- ;**************************************************************************
31
+ <<~PREAMBLE
32
+ ;**************************************************************************
33
+ ;** Title: #{title}
34
+ ;** Tempo: #{tempo}
35
+ ;** Encoded: #{encoding_date} with #{encoding_software}
36
+ ;** Stringyfied: #{Time.now}
37
+ ;**************************************************************************
35
38
 
36
- \ttstart DemoTune
37
- EOS
39
+ \ttstart DemoTune
40
+ PREAMBLE
38
41
  end
39
42
 
40
43
  def score_coda
41
- <<-EOS
42
- \ttrest 8
43
- \ttstop
44
- EOS
44
+ <<~CODA
45
+ \ttrest 8
46
+ \ttstop
47
+ CODA
45
48
  end
46
49
 
47
50
  def score_body(shortest_fractional_duration)
48
51
  lines = []
49
52
  current_octave = INITIAL_OCTAVE + OCTAVE_OFFSET
50
53
  measures.each_with_index do |measure, measure_index|
51
- lines << "\t; measure #{measure_index+1}"
54
+ lines << "\t; measure #{measure_index + 1}"
52
55
  measure.each do |note|
53
56
  unless note.rest?
54
57
  if note.octave != current_octave
55
58
  delta = note.octave - current_octave
56
- sign = delta > 0 ? "+" : "-"
57
- (delta.abs).times do
59
+ sign = delta.positive? ? '+' : '-'
60
+ delta.abs.times do
58
61
  lines << "\ttoctave #{sign}1"
59
62
  end
60
63
  current_octave = note.octave
@@ -62,15 +65,15 @@ EOS
62
65
  end
63
66
  short_repeats, medium_repeats, long_repeats, very_long_repeats = note.stringy_durations(shortest_fractional_duration)
64
67
  if note.rest?
65
- (short_repeats).times { lines << "\ttrest 1" }
66
- (medium_repeats).times { lines << "\ttrest 2" }
67
- (long_repeats).times { lines << "\ttrest 3" }
68
- (very_long_repeats).times { lines << "\ttrest 4" }
68
+ short_repeats.times { lines << "\ttrest 1" }
69
+ medium_repeats.times { lines << "\ttrest 2" }
70
+ long_repeats.times { lines << "\ttrest 3" }
71
+ very_long_repeats.times { lines << "\ttrest 4" }
69
72
  else
70
- (short_repeats).times { lines << "\ttnote #{note.to_stringy(current_octave)},1,0 ; #{note.to_note_id}" }
71
- (medium_repeats).times { lines << "\ttnote #{note.to_stringy(current_octave)},2,0 ; #{note.to_note_id}" }
72
- (long_repeats).times { lines << "\ttnote #{note.to_stringy(current_octave)},3,0 ; #{note.to_note_id}" }
73
- (very_long_repeats).times { lines << "\ttnote #{note.to_stringy(current_octave)},4,0 ; #{note.to_note_id}" }
73
+ short_repeats.times { lines << "\ttnote #{note.to_stringy(current_octave)},1,0 ; #{note.to_note_id}" }
74
+ medium_repeats.times { lines << "\ttnote #{note.to_stringy(current_octave)},2,0 ; #{note.to_note_id}" }
75
+ long_repeats.times { lines << "\ttnote #{note.to_stringy(current_octave)},3,0 ; #{note.to_note_id}" }
76
+ very_long_repeats.times { lines << "\ttnote #{note.to_stringy(current_octave)},4,0 ; #{note.to_note_id}" }
74
77
  end
75
78
  end
76
79
  end
@@ -104,8 +107,9 @@ EOS
104
107
  }
105
108
  }
106
109
  end
110
+
107
111
  def part_list
108
- xml_doc.xpath('//part-list/score-part').each_with_object([]) do |part,memo|
112
+ xml_doc.xpath('//part-list/score-part').each_with_object([]) do |part, memo|
109
113
  h = {}
110
114
  h[:id] = part.attr('id')
111
115
  memo << h
@@ -126,16 +130,15 @@ EOS
126
130
  part.xpath('measure').each_with_index do |part_measure, m|
127
131
  measures[m] ||= []
128
132
  part_measure.xpath('note').each_with_object(measures[m]) do |note, memo|
129
- next unless note.xpath("staff").text == "1"
130
- next unless note.xpath("voice").text == "1"
131
- pitch = note.xpath("pitch")
132
- duration = note.xpath("duration").text.to_i
133
- actual_notes = note.xpath("actual-notes").text.to_i
134
- normal_notes = note.xpath("normal-notes").text.to_i
135
- if actual_notes > 0 and normal_notes > 0
136
- duration = duration * 1.0 * normal_notes / actual_notes
137
- end
138
- duration_type = note.xpath("type").text
133
+ next unless note.xpath('staff').text == '1'
134
+ next unless note.xpath('voice').text == '1'
135
+
136
+ pitch = note.xpath('pitch')
137
+ duration = note.xpath('duration').text.to_i
138
+ actual_notes = note.xpath('actual-notes').text.to_i
139
+ normal_notes = note.xpath('normal-notes').text.to_i
140
+ duration = duration * 1.0 * normal_notes / actual_notes if actual_notes.positive? && normal_notes.positive?
141
+ duration_type = note.xpath('type').text
139
142
  memo << StringyFi::Note.new(
140
143
  pitch.xpath('step').text,
141
144
  pitch.xpath('octave').text,
@@ -160,5 +163,4 @@ EOS
160
163
  def io_stream
161
164
  File.open(filename).read
162
165
  end
163
-
164
- end
166
+ end
@@ -1,5 +1,7 @@
1
- class StringyFi::Measures < Array
1
+ # frozen_string_literal: true
2
2
 
3
+ # extend Array with methods for working with measures
4
+ class StringyFi::Measures < Array
3
5
  def shortest_fractional_duration
4
6
  result = 1
5
7
  each do |measure|
@@ -11,10 +13,11 @@ class StringyFi::Measures < Array
11
13
  end
12
14
 
13
15
  def octave_range
14
- lo = hi = nil
16
+ lo = hi = nil
15
17
  each do |measure|
16
18
  measure.each do |note|
17
19
  next if note.rest?
20
+
18
21
  lo ||= note.octave
19
22
  hi ||= note.octave
20
23
  lo = note.octave if note.octave < lo
@@ -23,5 +26,4 @@ class StringyFi::Measures < Array
23
26
  end
24
27
  [lo, hi]
25
28
  end
26
-
27
29
  end
@@ -1,41 +1,44 @@
1
- class StringyFi::Note
1
+ # frozen_string_literal: true
2
2
 
3
- attr_accessor :name, :octave, :alter
4
- attr_accessor :tempo
5
- attr_accessor :fractional_duration
3
+ # Represents a musical note
4
+ class StringyFi::Note
5
+ attr_accessor :name, :octave, :alter, :tempo, :fractional_duration
6
6
 
7
- def initialize(name, octave=4, alter=nil, duration=1, duration_type="quarter")
8
- self.name = "#{name}".upcase
9
- self.octave = "#{octave}".to_i
10
- self.alter = alter.to_i rescue 0
7
+ def initialize(name, octave = 4, alter = nil, duration = 1, duration_type = 'quarter')
8
+ self.name = name.to_s.upcase
9
+ self.octave = octave.to_s.to_i
10
+ self.alter = begin
11
+ alter.to_i
12
+ rescue StandardError
13
+ 0
14
+ end
11
15
  self.fractional_duration = calculate_fractional_duration(duration, duration_type)
12
16
  end
13
17
 
14
18
  def rest?
15
- name == ""
19
+ name == ''
16
20
  end
17
21
 
18
22
  def calculate_fractional_duration(duration, duration_type)
19
23
  divisor = {
20
- "half" => 2.0,
21
- "quarter" => 4.0,
22
- "eighth" => 8.0,
23
- "16th" => 16.0,
24
- "32nd" => 32.0
24
+ 'half' => 2.0,
25
+ 'quarter' => 4.0,
26
+ 'eighth' => 8.0,
27
+ '16th' => 16.0,
28
+ '32nd' => 32.0
25
29
  }[duration_type] || 1.0
26
- duration/divisor
30
+ duration / divisor
27
31
  end
28
32
 
29
- # retrun [short, medium, long, very_long] repeats for the note
33
+ # return [short, medium, long, very_long] repeats for the note
30
34
  # TODO: scale medium, long, very_long durations correctly
31
35
  def stringy_durations(shortest_fractional_duration)
32
36
  time_units = (fractional_duration / shortest_fractional_duration).to_i
33
- case
34
- when time_units >= 8
37
+ if time_units >= 8
35
38
  [0, 0, 0, 1]
36
- when time_units >= 4
39
+ elsif time_units >= 4
37
40
  [0, 0, 1, 0]
38
- when time_units >= 2
41
+ elsif time_units >= 2
39
42
  [0, 1, 0, 0]
40
43
  else
41
44
  [1, 0, 0, 0]
@@ -53,7 +56,7 @@ class StringyFi::Note
53
56
  'E' => 'D',
54
57
  'A' => 'G',
55
58
  'D' => 'C',
56
- 'G' => 'F',
59
+ 'G' => 'F'
57
60
  }[name]
58
61
  "#{sharpy_name}#{relative_octave}S"
59
62
  else
@@ -91,7 +94,6 @@ class StringyFi::Note
91
94
  end
92
95
 
93
96
  def <=>(other)
94
- self.to_note_id <=> other.to_note_id
97
+ to_note_id <=> other.to_note_id
95
98
  end
96
-
97
99
  end
@@ -1,8 +1,10 @@
1
- class StringyFi::Shell
1
+ # frozen_string_literal: true
2
2
 
3
+ # CLI support
4
+ class StringyFi::Shell
3
5
  attr_accessor :converter
4
6
 
5
- def initialize(args=[])
7
+ def initialize(args = [])
6
8
  filename = args.first || File.join(File.dirname(__FILE__), '..', '..', 'spec', 'fixtures', 'music_xml', 'chromatic.xml')
7
9
  self.converter = StringyFi::Converter.new(filename)
8
10
  end
@@ -10,4 +12,4 @@ class StringyFi::Shell
10
12
  def convert!
11
13
  converter.convert!
12
14
  end
13
- end
15
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module StringyFi
2
- VERSION = "0.0.1"
4
+ VERSION = '0.0.2'
3
5
  end
data/lib/stringyfi.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'stringyfi/version'
2
4
  require 'stringyfi/shell'
3
5
  require 'stringyfi/note'
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'stringyfi'
2
4
 
3
5
  # Requires supporting files with custom matchers and macros, etc,
4
6
  # in ./support/ and its subdirectories.
5
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
6
-
7
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
7
8
 
8
9
  # This file was generated by the `rspec --init` command. Conventionally, all
9
10
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
@@ -1,6 +1,7 @@
1
- module FixturesHelper
1
+ # frozen_string_literal: true
2
2
 
3
- def xml_sample_path(name='chromatic.xml')
3
+ module FixturesHelper
4
+ def xml_sample_path(name = 'chromatic.xml')
4
5
  File.join(xml_samples_path, name)
5
6
  end
6
7
 
@@ -11,4 +12,4 @@ end
11
12
 
12
13
  RSpec.configure do |conf|
13
14
  conf.include FixturesHelper
14
- end
15
+ end
@@ -1,89 +1,91 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe StringyFi::Converter do
4
6
  subject(:converter) { described_class.new(filename) }
5
7
 
6
- context "with chromatic.xml sample" do
8
+ context 'with chromatic.xml sample' do
7
9
  let(:filename) { xml_sample_path }
8
10
 
9
- describe "#xml_doc" do
11
+ describe '#xml_doc' do
10
12
  subject { converter.xml_doc }
11
- it "returns the XML doc" do
13
+ it 'returns the XML doc' do
12
14
  expect(subject).to be_a(Nokogiri::XML::Document)
13
15
  end
14
16
  end
15
17
 
16
- describe "#identification" do
18
+ describe '#identification' do
17
19
  subject(:identification) { converter.identification }
18
- it "returns expected metadata" do
20
+ it 'returns expected metadata' do
19
21
  expect(subject).to eql({
20
- title: "chromatic scale",
22
+ title: 'chromatic scale',
21
23
  encoding: {
22
- date: "2017-10-15",
23
- software: "Guitar Pro 7.0.6"
24
+ date: '2017-10-15',
25
+ software: 'Guitar Pro 7.0.6'
24
26
  }
25
27
  })
26
28
  end
27
29
  end
28
30
 
29
- describe "#part_list" do
31
+ describe '#part_list' do
30
32
  subject(:part_list) { converter.part_list }
31
- it "returns an array of parts" do
33
+ it 'returns an array of parts' do
32
34
  expect(part_list).to eql([
33
- {id: "P1"}
35
+ { id: 'P1' }
34
36
  ])
35
37
  end
36
38
  end
37
39
 
38
- describe "#parts" do
40
+ describe '#parts' do
39
41
  subject(:parts) { converter.parts }
40
- it "returns parts corresponding to parts list" do
42
+ it 'returns parts corresponding to parts list' do
41
43
  expect(parts.count).to eql(converter.part_list.count)
42
44
  end
43
45
  end
44
46
 
45
- describe "#measures" do
47
+ describe '#measures' do
46
48
  subject(:measures) { converter.measures }
47
- it "has the correct number of measures" do
49
+ it 'has the correct number of measures' do
48
50
  expect(measures).to be_a(StringyFi::Measures)
49
51
  expect(measures.count).to eql(7)
50
52
  end
51
53
  end
52
54
 
53
- describe "#measure" do
55
+ describe '#measure' do
54
56
  subject(:measure) { converter.measure(measure_id) }
55
- context "with first measure" do
57
+ context 'with first measure' do
56
58
  let(:measure_id) { 0 }
57
- it "has the correct note info" do
59
+ it 'has the correct note info' do
58
60
  expect(measure).to be_an(Array)
59
61
  expect(measure.size).to eql(1)
60
62
  expect(measure[0]).to be_a(StringyFi::Note)
61
- expect(measure[0].to_str).to eql("3:E:0")
63
+ expect(measure[0].to_str).to eql('3:E:0')
62
64
  end
63
65
  end
64
66
  end
65
67
 
66
- describe "#score_preamble" do
68
+ describe '#score_preamble' do
67
69
  subject { converter.score_preamble }
68
- it "includes the expected identification" do
70
+ it 'includes the expected identification' do
69
71
  expect(subject).to include(';** Title: chromatic scale')
70
72
  end
71
- it "includes the tstart" do
73
+ it 'includes the tstart' do
72
74
  expect(subject).to include("\ttstart DemoTune")
73
75
  end
74
76
  end
75
77
 
76
- describe "#score_coda" do
78
+ describe '#score_coda' do
77
79
  subject { converter.score_coda }
78
- it "includes a rest and tstop" do
80
+ it 'includes a rest and tstop' do
79
81
  expect(subject).to include("\ttrest 8")
80
82
  expect(subject).to include("\ttstop")
81
83
  end
82
84
  end
83
85
 
84
- describe "#score_body" do
85
- subject { converter.score_body(1/32.0) }
86
- it "returns the expected conversion" do
86
+ describe '#score_body' do
87
+ subject { converter.score_body(1 / 32.0) }
88
+ it 'returns the expected conversion' do
87
89
  expect(subject).to eql([
88
90
  "\t; measure 1",
89
91
  "\ttoctave -1",
@@ -150,9 +152,9 @@ describe StringyFi::Converter do
150
152
  end
151
153
  end
152
154
 
153
- describe "#convert!" do
155
+ describe '#convert!' do
154
156
  subject { converter.convert! }
155
- it "calls all the necessary bits" do
157
+ it 'calls all the necessary bits' do
156
158
  expect(converter).to receive(:score_preamble)
157
159
  expect(converter).to receive(:score_body)
158
160
  expect(converter).to receive(:score_coda)
@@ -161,6 +163,5 @@ describe StringyFi::Converter do
161
163
  subject
162
164
  end
163
165
  end
164
-
165
166
  end
166
167
  end
@@ -1,34 +1,34 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe StringyFi::Measures do
4
-
5
6
  let(:note_class) { StringyFi::Note }
6
7
  let(:measures) { described_class.new }
7
8
 
8
9
  before do
9
10
  measures << [
10
- note_class.new('G', 4, 1, 1, "half"),
11
- note_class.new('G', 2, 0, 1, "quarter")
11
+ note_class.new('G', 4, 1, 1, 'half'),
12
+ note_class.new('G', 2, 0, 1, 'quarter')
12
13
  ]
13
14
  measures << [
14
- note_class.new('G', 3, 0, 1, "whole"),
15
- note_class.new('A', 4, 0, 1, "32nd"),
16
- note_class.new('G', 4, 1, 1, "eighth")
15
+ note_class.new('G', 3, 0, 1, 'whole'),
16
+ note_class.new('A', 4, 0, 1, '32nd'),
17
+ note_class.new('G', 4, 1, 1, 'eighth')
17
18
  ]
18
19
  end
19
20
 
20
- describe "#shortest_fractional_duration" do
21
+ describe '#shortest_fractional_duration' do
21
22
  subject { measures.shortest_fractional_duration }
22
- it "returns the shortest of any note" do
23
- expect(subject).to eql(1/32.0)
23
+ it 'returns the shortest of any note' do
24
+ expect(subject).to eql(1 / 32.0)
24
25
  end
25
26
  end
26
27
 
27
- describe "#octave_range" do
28
+ describe '#octave_range' do
28
29
  subject { measures.octave_range }
29
- it "returns the lowest and highest as an array" do
30
+ it 'returns the lowest and highest as an array' do
30
31
  expect(subject).to eql([2, 4])
31
32
  end
32
33
  end
33
-
34
- end
34
+ end
@@ -1,51 +1,52 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe StringyFi::Note do
4
-
5
6
  let(:name) { 'G' }
6
7
  let(:octave) { '4' }
7
8
  let(:alter) { nil }
8
9
  let(:duration) { 1 }
9
- let(:duration_type) { "quarter" }
10
+ let(:duration_type) { 'quarter' }
10
11
  subject(:note) { described_class.new(name, octave, alter, duration, duration_type) }
11
12
 
12
-
13
- describe "#stringy_durations" do
14
- subject { note.stringy_durations(shortest_fractional_duration)}
15
- context "when quarter is shortest" do
16
- let(:shortest_fractional_duration) { 1/4.0 }
13
+ describe '#stringy_durations' do
14
+ subject { note.stringy_durations(shortest_fractional_duration) }
15
+ context 'when quarter is shortest' do
16
+ let(:shortest_fractional_duration) { 1 / 4.0 }
17
17
  [
18
- {duration: 1, duration_type: "quarter", expect: [1, 0, 0, 0]},
19
- {duration: 2, duration_type: "quarter", expect: [0, 1, 0, 0]},
20
- {duration: 3, duration_type: "quarter", expect: [0, 1, 0, 0]},
21
- {duration: 4, duration_type: "quarter", expect: [0, 0, 1, 0]},
22
- {duration: 5, duration_type: "quarter", expect: [0, 0, 1, 0]},
23
- {duration: 6, duration_type: "quarter", expect: [0, 0, 1, 0]},
24
- {duration: 7, duration_type: "quarter", expect: [0, 0, 1, 0]},
25
- {duration: 1, duration_type: "half", expect: [0, 1, 0, 0]},
26
- {duration: 4, duration_type: "half", expect: [0, 0, 0, 1]},
27
- {duration: 1, duration_type: "whole", expect: [0, 0, 1, 0]},
28
- {duration: 2, duration_type: "whole", expect: [0, 0, 0, 1]},
18
+ { duration: 1, duration_type: 'quarter', expect: [1, 0, 0, 0] },
19
+ { duration: 2, duration_type: 'quarter', expect: [0, 1, 0, 0] },
20
+ { duration: 3, duration_type: 'quarter', expect: [0, 1, 0, 0] },
21
+ { duration: 4, duration_type: 'quarter', expect: [0, 0, 1, 0] },
22
+ { duration: 5, duration_type: 'quarter', expect: [0, 0, 1, 0] },
23
+ { duration: 6, duration_type: 'quarter', expect: [0, 0, 1, 0] },
24
+ { duration: 7, duration_type: 'quarter', expect: [0, 0, 1, 0] },
25
+ { duration: 1, duration_type: 'half', expect: [0, 1, 0, 0] },
26
+ { duration: 4, duration_type: 'half', expect: [0, 0, 0, 1] },
27
+ { duration: 1, duration_type: 'whole', expect: [0, 0, 1, 0] },
28
+ { duration: 2, duration_type: 'whole', expect: [0, 0, 0, 1] }
29
29
  ].each do |options|
30
30
  context "and duration=#{options[:duration]}-#{options[:duration_type]}" do
31
31
  let(:duration) { options[:duration] }
32
32
  let(:duration_type) { options[:duration_type] }
33
- it "returns expected repeats/remainder" do
33
+ it 'returns expected repeats/remainder' do
34
34
  expect(subject).to eql(options[:expect])
35
35
  end
36
36
  end
37
37
  end
38
38
  end
39
- context "when 32nd is shortest" do
40
- let(:shortest_fractional_duration) { 1/32.0 }
39
+
40
+ context 'when 32nd is shortest' do
41
+ let(:shortest_fractional_duration) { 1 / 32.0 }
41
42
  [
42
- {duration: 1, duration_type: "32nd", expect: [1, 0, 0, 0]},
43
- {duration: 1, duration_type: "quarter", expect: [0, 0, 0, 1]},
43
+ { duration: 1, duration_type: '32nd', expect: [1, 0, 0, 0] },
44
+ { duration: 1, duration_type: 'quarter', expect: [0, 0, 0, 1] }
44
45
  ].each do |options|
45
46
  context "and duration=#{options[:duration]}-#{options[:duration_type]}" do
46
47
  let(:duration) { options[:duration] }
47
48
  let(:duration_type) { options[:duration_type] }
48
- it "returns expected repeats/remainder" do
49
+ it 'returns expected repeats/remainder' do
49
50
  expect(subject).to eql(options[:expect])
50
51
  end
51
52
  end
@@ -53,54 +54,53 @@ describe StringyFi::Note do
53
54
  end
54
55
  end
55
56
 
56
- describe "#to_s" do
57
+ describe '#to_s' do
57
58
  subject { note.to_s }
58
- context "when not altered" do
59
- it { should eql('G')}
59
+ context 'when not altered' do
60
+ it { should eql('G') }
60
61
  end
61
- context "when altered up" do
62
+ context 'when altered up' do
62
63
  let(:alter) { 1 }
63
- it { should eql('G#')}
64
+ it { should eql('G#') }
64
65
  end
65
- context "when altered down" do
66
+ context 'when altered down' do
66
67
  let(:alter) { -1 }
67
- it { should eql('Gb')}
68
+ it { should eql('Gb') }
68
69
  end
69
70
  end
70
71
 
71
- describe "#to_str" do
72
+ describe '#to_str' do
72
73
  subject { note.to_str }
73
- context "when not altered" do
74
- it { should eql('4:G:0')}
74
+ context 'when not altered' do
75
+ it { should eql('4:G:0') }
75
76
  end
76
- context "when altered up" do
77
+ context 'when altered up' do
77
78
  let(:alter) { 1 }
78
- it { should eql('4:G:1')}
79
+ it { should eql('4:G:1') }
79
80
  end
80
- context "when altered down" do
81
+ context 'when altered down' do
81
82
  let(:alter) { -1 }
82
- it { should eql('4:G:-1')}
83
+ it { should eql('4:G:-1') }
83
84
  end
84
85
  end
85
86
 
86
- describe "#<=>" do
87
+ describe '#<=>' do
87
88
  let(:other_name) { name }
88
89
  let(:other_octave) { octave }
89
90
  let(:other_alter) { alter }
90
91
  let(:other_note) { described_class.new(other_name, other_octave, other_alter) }
91
92
 
92
93
  subject { note <=> other_note }
93
- context "when same" do
94
+ context 'when same' do
94
95
  it { should eql(0) }
95
96
  end
96
- context "when vary by alter up" do
97
+ context 'when vary by alter up' do
97
98
  let(:other_alter) { 1 }
98
99
  it { should eql(-1) }
99
100
  end
100
- context "when vary by octave down" do
101
+ context 'when vary by octave down' do
101
102
  let(:other_octave) { 3 }
102
103
  it { should eql(1) }
103
104
  end
104
105
  end
105
-
106
106
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe StringyFi::Shell do
4
6
  subject(:shell) { described_class.new }
5
7
 
6
- context "when no args passed" do
7
- it "initialises with sample fixture" do
8
+ context 'when no args passed' do
9
+ it 'initialises with sample fixture' do
8
10
  expect(subject).to be_a(described_class)
9
- expect(subject.converter.filename).to include("chromatic.xml")
11
+ expect(subject.converter.filename).to include('chromatic.xml')
10
12
  end
11
13
  end
12
- end
14
+ end
@@ -1,9 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe StringyFi do
4
-
5
- it "has a version" do
6
+ it 'has a version' do
6
7
  expect(described_class::VERSION).to match(/\d+\.\d+\.\d+/)
7
8
  end
8
-
9
- end
9
+ end
data/stringyfi.gemspec CHANGED
@@ -1,31 +1,23 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
5
  require 'stringyfi/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "stringyfi"
8
+ spec.name = 'stringyfi'
8
9
  spec.version = StringyFi::VERSION
9
- spec.authors = ["Paul Gallagher"]
10
- spec.email = ["gallagher.paul@gmail.com"]
11
- spec.summary = "Convert MusicXML to PIC assembler for the Boldport Stringy"
12
- spec.homepage = "https://github.com/tardate/stringyfi"
13
- spec.license = "MIT"
10
+ spec.authors = ['Paul Gallagher']
11
+ spec.email = ['gallagher.paul@gmail.com']
12
+ spec.summary = 'Convert MusicXML to PIC assembler for the Boldport Stringy'
13
+ spec.homepage = 'https://github.com/tardate/stringyfi'
14
+ spec.license = 'MIT'
14
15
 
15
16
  spec.files = `git ls-files -z`.split("\x0")
16
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
- spec.require_paths = ["lib"]
19
-
20
- spec.add_runtime_dependency "nokogiri", "~> 1.8"
21
-
22
- spec.add_development_dependency "bundler", "~> 1.6"
23
- spec.add_development_dependency "rake"
24
- spec.add_development_dependency "rspec"
19
+ spec.require_paths = ['lib']
25
20
 
26
- # guard versions are pegged to avoid issue with ruby_dep requires Ruby version >= 2.2.5, ~> 2.2.
27
- spec.add_development_dependency "guard-rspec", "4.6.4"
28
- spec.add_development_dependency "rb-fsevent", "0.9.6"
29
- spec.add_development_dependency "rb-inotify", "0.9.5"
30
- spec.add_development_dependency "pry-coolline", "0.2.5" # avoid readline dependency
21
+ spec.required_ruby_version = '>= 3.0'
22
+ spec.add_runtime_dependency 'nokogiri', '~> 1.18'
31
23
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stringyfi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Gallagher
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2017-10-16 00:00:00.000000000 Z
10
+ date: 2025-07-29 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: nokogiri
@@ -16,113 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: '1.8'
18
+ version: '1.18'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: '1.8'
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.6'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.6'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: rspec
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: guard-rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - '='
74
- - !ruby/object:Gem::Version
75
- version: 4.6.4
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - '='
81
- - !ruby/object:Gem::Version
82
- version: 4.6.4
83
- - !ruby/object:Gem::Dependency
84
- name: rb-fsevent
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - '='
88
- - !ruby/object:Gem::Version
89
- version: 0.9.6
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - '='
95
- - !ruby/object:Gem::Version
96
- version: 0.9.6
97
- - !ruby/object:Gem::Dependency
98
- name: rb-inotify
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - '='
102
- - !ruby/object:Gem::Version
103
- version: 0.9.5
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - '='
109
- - !ruby/object:Gem::Version
110
- version: 0.9.5
111
- - !ruby/object:Gem::Dependency
112
- name: pry-coolline
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - '='
116
- - !ruby/object:Gem::Version
117
- version: 0.2.5
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - '='
123
- - !ruby/object:Gem::Version
124
- version: 0.2.5
125
- description:
25
+ version: '1.18'
126
26
  email:
127
27
  - gallagher.paul@gmail.com
128
28
  executables:
@@ -130,11 +30,11 @@ executables:
130
30
  extensions: []
131
31
  extra_rdoc_files: []
132
32
  files:
33
+ - ".github/workflows/ruby-tests.yml"
133
34
  - ".gitignore"
134
- - ".rspec"
35
+ - ".rubocop.yml"
135
36
  - ".ruby-gemset"
136
37
  - ".ruby-version"
137
- - ".travis.yml"
138
38
  - Gemfile
139
39
  - Guardfile
140
40
  - LICENSE.txt
@@ -163,7 +63,6 @@ homepage: https://github.com/tardate/stringyfi
163
63
  licenses:
164
64
  - MIT
165
65
  metadata: {}
166
- post_install_message:
167
66
  rdoc_options: []
168
67
  require_paths:
169
68
  - lib
@@ -171,16 +70,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
171
70
  requirements:
172
71
  - - ">="
173
72
  - !ruby/object:Gem::Version
174
- version: '0'
73
+ version: '3.0'
175
74
  required_rubygems_version: !ruby/object:Gem::Requirement
176
75
  requirements:
177
76
  - - ">="
178
77
  - !ruby/object:Gem::Version
179
78
  version: '0'
180
79
  requirements: []
181
- rubyforge_project:
182
- rubygems_version: 2.6.12
183
- signing_key:
80
+ rubygems_version: 3.6.2
184
81
  specification_version: 4
185
82
  summary: Convert MusicXML to PIC assembler for the Boldport Stringy
186
83
  test_files:
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --format documentation
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- # These are specific configuration settings required for travis-ci
2
- # see http://travis-ci.org/tardate/stringyfi
3
- language: ruby
4
- rvm:
5
- - 2.4.1