diagram 0.2.1

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