diagram 0.2.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6ef3c343a2636e4f7ffda61678ff784b5d0b083d25ab83364e0285cb5c150acd
4
+ data.tar.gz: 9988256feb04b4eee350d792cc697cdb3bee87371a0211f5f714a4f1c380d2e8
5
+ SHA512:
6
+ metadata.gz: b9bf6af4e963b22981ce1eec3205e1d35e3a25752183fc2b91b1650148e3eb08f738522535b6234eca33cab21be7070132f8f41f4dff9663fa35bff8cf1d742d
7
+ data.tar.gz: 4ce8d1844a7bd0c961a89ed838d3541cbf10a9794f897622aea05f81b654937acc9054c7a09a114d625e22bfe12af524ea7832e3a20a1f40f0ca1e9c39548fb1
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ # Abstract class for diagrams
5
+ class AbstractDiagram < Dry::Struct
6
+ module Types
7
+ include Dry.Types()
8
+ end
9
+
10
+ def initialize(*)
11
+ raise NotImplementedError, 'Cannot instantiate abstract class' if instance_of?(AbstractDiagram)
12
+
13
+ super
14
+ end
15
+
16
+ def type
17
+ raise NotImplementedError, 'Subclasses must define `type`.'
18
+ end
19
+
20
+ ## Errors
21
+ class ValidationError < StandardError; end
22
+ class EmptyDiagramError < ValidationError; end
23
+ class InvalidPercentageError < ValidationError; end
24
+ class DuplicateLabelError < ValidationError; end
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class ClassDiagram
5
+ class Class
6
+ class Field < Dry::Struct
7
+ attribute :name, ClassDiagram::Types::String
8
+ attribute :type, ClassDiagram::Types::String.optional.default('String')
9
+ attribute :visibility,
10
+ ClassDiagram::Types::String.optional.default('public')
11
+ .constrained(format: /\A(public|private|protected|Internal)\z/)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class ClassDiagram
5
+ class Class
6
+ class Function
7
+ class Argument < Dry::Struct
8
+ attribute :name, ClassDiagram::Types::String
9
+ attribute :type, ClassDiagram::Types::String.optional.default(nil)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class ClassDiagram
5
+ class Class
6
+ class Function < Dry::Struct
7
+ attribute :name, ClassDiagram::Types::String
8
+ attribute :return_type, ClassDiagram::Types::String.optional.default('void')
9
+ attribute :arguments, ClassDiagram::Types::Array.of(Argument)
10
+ attribute :visibility,
11
+ ClassDiagram::Types::String.optional.default('public')
12
+ .constrained(format: /\A(public|private|protected)\z/)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class ClassDiagram
5
+ class Class < Dry::Struct
6
+ attribute :id, ClassDiagram::Types::String.constrained(format: /\A[a-zA-Z0-9_-]+\z/)
7
+ attribute :label, ClassDiagram::Types::String.optional.default(nil)
8
+ attribute :fields, ClassDiagram::Types::Array.of(Field)
9
+ attribute :functions, ClassDiagram::Types::Array.of(Function)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class ClassDiagram < AbstractDiagram
5
+ attribute :classes, ClassDiagram::Types::Array.of(Class)
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ module Comparable
5
+ def ==(other)
6
+ other.class == self.class && other.state == state
7
+ end
8
+ alias eql? ==
9
+
10
+ def hash
11
+ state.hash
12
+ end
13
+
14
+ protected
15
+
16
+ def state
17
+ instance_variables.map { |name| instance_variable_get(name) }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class FlowchartDiagram
5
+ class Link < Dry::Struct
6
+ attribute :from, FlowchartDiagram::Types::String
7
+ attribute :to, FlowchartDiagram::Types::String
8
+ attribute :label, FlowchartDiagram::Types::String.optional.default(nil)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class FlowchartDiagram
5
+ class Node < Dry::Struct
6
+ attribute :id, FlowchartDiagram::Types::String
7
+ attribute :label, FlowchartDiagram::Types::String
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class FlowchartDiagram < AbstractDiagram
5
+ attribute :id, Types::String
6
+ attribute :nodes, Types::Array.of(Node)
7
+ attribute :links, Types::Array.of(Link)
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class GanttDiagram
5
+ class Section
6
+ class Task < Dry::Struct
7
+ attribute :name, GanttDiagram::Types::String
8
+ attribute :start, GanttDiagram::Types::String
9
+ attribute :end, GanttDiagram::Types::String
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class GanttDiagram
5
+ class Section < Dry::Struct
6
+ attribute :name, GanttDiagram::Types::String
7
+ attribute :tasks, GanttDiagram::Types::Array.of(Task)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class GanttDiagram < AbstractDiagram
5
+ attribute :title, GanttDiagram::Types::String
6
+ attribute :sections, GanttDiagram::Types::Array.of(Section)
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class PieDiagram
5
+ class Section < Dry::Struct
6
+ attribute :label, PieDiagram::Types::String.optional.default(nil)
7
+ attribute :value, PieDiagram::Types::Coercible::Float.optional.default(0).constrained(gteq: 0)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class PieDiagram < AbstractDiagram
5
+ attribute :id, Types::String.optional.default(nil)
6
+ attribute :title, Types::String.optional.default('')
7
+ attribute :sections, Types::Array.of(Section).optional.default([].freeze)
8
+
9
+ def type
10
+ :pie
11
+ end
12
+
13
+ def validate!
14
+ raise EmptyDiagramError, 'Pie diagram must have at least one section' if sections.empty?
15
+
16
+ return true if sections.map(&:label).uniq.size == sections.size
17
+
18
+ raise DuplicateLabelError,
19
+ 'Pie diagram sections must have unique labels'
20
+ end
21
+
22
+ def plot
23
+ circle_char = '*'
24
+ pie_diameter = 10
25
+ pie_radius = pie_diameter / 2.0
26
+
27
+ (-pie_radius.to_i..pie_radius.to_i).each do |i|
28
+ (-pie_radius.to_i..pie_radius.to_i).each do |j|
29
+ distance_to_center = Math.sqrt((i**2) + (j**2))
30
+ if distance_to_center > pie_radius - 0.5 && distance_to_center < pie_radius + 0.5
31
+ print circle_char
32
+ else
33
+ print ' '
34
+ end
35
+ end
36
+ print "\n"
37
+ end
38
+
39
+ sections.each do |section|
40
+ puts "#{section.label}: #{section.value}%"
41
+ end
42
+ end
43
+
44
+ def valid?
45
+ validate!
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ module Plot
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def plottable?
11
+ true
12
+ end
13
+ end
14
+
15
+ def plottable?
16
+ self.class.plottable?
17
+ end
18
+
19
+ def plot
20
+ raise NotImplementedError
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class StateDiagram
5
+ class Event < Dry::Struct
6
+ attribute :id, StateDiagram::Types::String
7
+ attribute :label, StateDiagram::Types::String.optional.default(nil)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class StateDiagram
5
+ class State < Dry::Struct
6
+ attribute :id, StateDiagram::Types::String
7
+ attribute :label, StateDiagram::Types::String.optional.default(nil)
8
+ attribute :type,
9
+ StateDiagram::Types::String.optional.default('state').enum('state', 'start', 'end', 'fork', 'join')
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class StateDiagram
5
+ class Transition < Dry::Struct
6
+ attribute :from, StateDiagram::Types::String
7
+ attribute :to, StateDiagram::Types::String
8
+ attribute :label, StateDiagram::Types::String.optional.default(nil)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ class StateDiagram < AbstractDiagram
5
+ attribute :id, Types::String
6
+ attribute :states, Types::Array.of(State)
7
+ attribute :transitions, Types::Array.of(Transition)
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Diagrams
4
+ VERSION = '0.2.1'
5
+ end
data/lib/diagrams.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'diagrams/version'
4
+ require 'dry-struct'
5
+
6
+ loader = Zeitwerk::Loader.for_gem
7
+ loader.setup
8
+
9
+ # This module handles diagrams creation and manipulation.
10
+ module Diagrams
11
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: diagram
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Abdelkader Boudih
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-02-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry-struct
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.0
27
+ description: Work with diagrams in Ruby
28
+ email:
29
+ - seuros@pre-history.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/diagrams.rb
35
+ - lib/diagrams/abstract_diagram.rb
36
+ - lib/diagrams/class_diagram.rb
37
+ - lib/diagrams/class_diagram/class.rb
38
+ - lib/diagrams/class_diagram/class/field.rb
39
+ - lib/diagrams/class_diagram/class/function.rb
40
+ - lib/diagrams/class_diagram/class/function/argument.rb
41
+ - lib/diagrams/comparable.rb
42
+ - lib/diagrams/flowchart_diagram.rb
43
+ - lib/diagrams/flowchart_diagram/link.rb
44
+ - lib/diagrams/flowchart_diagram/node.rb
45
+ - lib/diagrams/gantt_diagram.rb
46
+ - lib/diagrams/gantt_diagram/section.rb
47
+ - lib/diagrams/gantt_diagram/section/task.rb
48
+ - lib/diagrams/pie_diagram.rb
49
+ - lib/diagrams/pie_diagram/section.rb
50
+ - lib/diagrams/plot.rb
51
+ - lib/diagrams/state_diagram.rb
52
+ - lib/diagrams/state_diagram/event.rb
53
+ - lib/diagrams/state_diagram/state.rb
54
+ - lib/diagrams/state_diagram/transition.rb
55
+ - lib/diagrams/version.rb
56
+ homepage: https://github.com/seuros/diagram-ruby
57
+ licenses:
58
+ - MIT
59
+ metadata:
60
+ homepage_uri: https://github.com/seuros/diagram-ruby
61
+ source_code_uri: https://github.com/seuros/diagram-ruby
62
+ changelog_uri: https://github.com/seuros/diagram-ruby/blob/master/CHANGELOG.md
63
+ rubygems_mfa_required: 'true'
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 3.1.0
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubygems_version: 3.4.10
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Work with diagrams in Ruby
83
+ test_files: []