From d15949c414545d6deb0e00bf9cb59a22a39db9c8 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sat, 30 Dec 2023 03:45:09 +0200 Subject: [PATCH] add ruby egzas --- lab2/main.go | 17 +- ruby-egzas/IF-1-1_PuzonasR_dat_1.json | 42 +++++ ruby-egzas/IF-1-1_PuzonasR_dat_2.json | 42 +++++ ruby-egzas/IF-1-1_PuzonasR_dat_3.json | 42 +++++ ruby-egzas/README.md | 3 + ruby-egzas/main.rb | 220 ++++++++++++++++++++++++++ 6 files changed, 357 insertions(+), 9 deletions(-) create mode 100644 ruby-egzas/IF-1-1_PuzonasR_dat_1.json create mode 100644 ruby-egzas/IF-1-1_PuzonasR_dat_2.json create mode 100644 ruby-egzas/IF-1-1_PuzonasR_dat_3.json create mode 100644 ruby-egzas/README.md create mode 100644 ruby-egzas/main.rb diff --git a/lab2/main.go b/lab2/main.go index 243a10e..b7aeb38 100644 --- a/lab2/main.go +++ b/lab2/main.go @@ -54,7 +54,7 @@ func processEntry(entry DataEntry, output chan DataEntry) { } } -func dataThread(fromMain, toWorker chan DataEntry, workerRequest chan bool, arraySize int, workerCount int) { +func dataThread(fromMain, toWorker chan DataEntry, fromWorkerRequest chan bool, arraySize int, workerCount int) { var gotTerminator = false var storage []DataEntry = make([]DataEntry, arraySize) var used = 0 @@ -69,7 +69,7 @@ func dataThread(fromMain, toWorker chan DataEntry, workerRequest chan bool, arra used += 1 } - var getFromStorage = func() DataEntry { + var removeFromStorage = func() DataEntry { var entry = storage[used-1] used -= 1 return entry @@ -77,31 +77,30 @@ func dataThread(fromMain, toWorker chan DataEntry, workerRequest chan bool, arra for { if (used == arraySize) { - <-workerRequest - toWorker <- getFromStorage() + <-fromWorkerRequest + toWorker <- removeFromStorage() } else if (used == 0) { appendtoStorage(<-fromMain) } else { select { case entry := <-fromMain: appendtoStorage(entry) - case <-workerRequest: - toWorker <- getFromStorage() + case <-fromWorkerRequest: + toWorker <- removeFromStorage() } } if (gotTerminator) { for i := 0; i < used; i++ { - <-workerRequest + <-fromWorkerRequest toWorker <- storage[i] } for i := 0; i < workerCount; i++ { - <-workerRequest + <-fromWorkerRequest toWorker <- Terminator } break } - } } diff --git a/ruby-egzas/IF-1-1_PuzonasR_dat_1.json b/ruby-egzas/IF-1-1_PuzonasR_dat_1.json new file mode 100644 index 0000000..6ea9fbf --- /dev/null +++ b/ruby-egzas/IF-1-1_PuzonasR_dat_1.json @@ -0,0 +1,42 @@ +[ + {"name":"Fruit juice 76","sugar":193.65132,"criteria":145}, + {"name":"Ice cream 16","sugar":186.08167,"criteria":132}, + {"name":"Smoothie 27","sugar":196.04042,"criteria":157}, + {"name":"Apple 88","sugar":142.26443,"criteria":82}, + {"name":"Ice cream 73","sugar":164.25926,"criteria":109}, + {"name":"Ice cream 71","sugar":148.9654,"criteria":136}, + {"name":"Tea 94","sugar":146.7983,"criteria":114}, + {"name":"Candy 14","sugar":189.80835,"criteria":145}, + {"name":"Fruit juice 48","sugar":149.91238,"criteria":105}, + {"name":"Smoothie 25","sugar":146.42593,"criteria":97}, + {"name":"Apple 23","sugar":124.13099,"criteria":90}, + {"name":"Ice cream 48","sugar":132.76225,"criteria":97}, + {"name":"Candy 12","sugar":166.74808,"criteria":136}, + {"name":"Fruit juice 0","sugar":159.86632,"criteria":138}, + {"name":"Cake 50","sugar":172.98724,"criteria":121}, + {"name":"Cake 22","sugar":102.71184,"criteria":58}, + {"name":"Smoothie 51","sugar":169.24905,"criteria":146}, + {"name":"Apple 13","sugar":197.4303,"criteria":176}, + {"name":"Cake 47","sugar":132.49425,"criteria":96}, + {"name":"Smoothie 75","sugar":117.34118,"criteria":70}, + {"name":"Apple 65","sugar":105.77017,"criteria":78}, + {"name":"Fruit juice 7","sugar":136.12982,"criteria":123}, + {"name":"Fruit juice 8","sugar":107.79159,"criteria":74}, + {"name":"Apple 20","sugar":100.0637,"criteria":62}, + {"name":"Chocolate 26","sugar":159.88702,"criteria":135}, + {"name":"Fruit juice 91","sugar":195.36041,"criteria":174}, + {"name":"Cake 12","sugar":170.92297,"criteria":145}, + {"name":"Cake 48","sugar":104.69248,"criteria":45}, + {"name":"Smoothie 95","sugar":107.425224,"criteria":57}, + {"name":"Ice cream 43","sugar":154.7334,"criteria":112}, + {"name":"Smoothie 42","sugar":124.851166,"criteria":96}, + {"name":"Ice cream 61","sugar":191.13419,"criteria":173}, + {"name":"Ice cream 52","sugar":123.938934,"criteria":75}, + {"name":"Ice cream 4","sugar":113.318596,"criteria":54}, + {"name":"Fruit juice 26","sugar":151.61147,"criteria":137}, + {"name":"Candy 61","sugar":139.66057,"criteria":90}, + {"name":"Smoothie 23","sugar":176.65881,"criteria":142}, + {"name":"Cake 11","sugar":198.92917,"criteria":185}, + {"name":"Apple 83","sugar":159.48036,"criteria":114}, + {"name":"Fruit juice 29","sugar":112.71098,"criteria":65} +] \ No newline at end of file diff --git a/ruby-egzas/IF-1-1_PuzonasR_dat_2.json b/ruby-egzas/IF-1-1_PuzonasR_dat_2.json new file mode 100644 index 0000000..0012dd6 --- /dev/null +++ b/ruby-egzas/IF-1-1_PuzonasR_dat_2.json @@ -0,0 +1,42 @@ +[ + {"name":"Tea 35","sugar":102.67245,"criteria":153}, + {"name":"Candy 45","sugar":160.1899,"criteria":119}, + {"name":"Fruit juice 14","sugar":104.17689,"criteria":78}, + {"name":"Candy 87","sugar":132.45172,"criteria":84}, + {"name":"Fruit juice 12","sugar":116.65934,"criteria":142}, + {"name":"Cake 37","sugar":101.45675,"criteria":161}, + {"name":"Cake 78","sugar":174.44292,"criteria":121}, + {"name":"Smoothie 20","sugar":146.48544,"criteria":175}, + {"name":"Tea 45","sugar":154.54736,"criteria":121}, + {"name":"Tea 9","sugar":161.4415,"criteria":191}, + {"name":"Cake 32","sugar":124.795944,"criteria":182}, + {"name":"Chocolate 12","sugar":180.10109,"criteria":147}, + {"name":"Apple 6","sugar":101.775,"criteria":143}, + {"name":"Chocolate 29","sugar":144.85179,"criteria":169}, + {"name":"Fruit juice 81","sugar":156.3534,"criteria":208}, + {"name":"Cake 51","sugar":114.41123,"criteria":148}, + {"name":"Tea 16","sugar":167.4808,"criteria":196}, + {"name":"Apple 92","sugar":166.1134,"criteria":119}, + {"name":"Candy 15","sugar":184.1573,"criteria":210}, + {"name":"Ice cream 79","sugar":109.4283,"criteria":138}, + {"name":"Apple 33","sugar":137.14066,"criteria":114}, + {"name":"Chocolate 86","sugar":190.01999,"criteria":248}, + {"name":"Fruit juice 2","sugar":198.52423,"criteria":164}, + {"name":"Tea 82","sugar":159.13023,"criteria":118}, + {"name":"Smoothie 31","sugar":158.44916,"criteria":200}, + {"name":"Tea 89","sugar":172.12093,"criteria":146}, + {"name":"Apple 22","sugar":118.49223,"criteria":154}, + {"name":"Fruit juice 81","sugar":146.55879,"criteria":94}, + {"name":"Tea 62","sugar":114.96604,"criteria":150}, + {"name":"Ice cream 10","sugar":117.40653,"criteria":93}, + {"name":"Fruit juice 62","sugar":169.27748,"criteria":188}, + {"name":"Cake 1","sugar":198.42546,"criteria":180}, + {"name":"Chocolate 39","sugar":172.85019,"criteria":217}, + {"name":"Apple 21","sugar":142.42413,"criteria":105}, + {"name":"Ice cream 73","sugar":114.56453,"criteria":152}, + {"name":"Tea 34","sugar":116.19339,"criteria":105}, + {"name":"Fruit juice 57","sugar":189.37839,"criteria":154}, + {"name":"Chocolate 63","sugar":107.178024,"criteria":72}, + {"name":"Cake 19","sugar":158.35861,"criteria":206}, + {"name":"Ice cream 29","sugar":154.20683,"criteria":99} +] \ No newline at end of file diff --git a/ruby-egzas/IF-1-1_PuzonasR_dat_3.json b/ruby-egzas/IF-1-1_PuzonasR_dat_3.json new file mode 100644 index 0000000..053eac6 --- /dev/null +++ b/ruby-egzas/IF-1-1_PuzonasR_dat_3.json @@ -0,0 +1,42 @@ +[ + {"name":"Tea 32","sugar":156.2579,"criteria":189}, + {"name":"Smoothie 75","sugar":138.6357,"criteria":162}, + {"name":"Fruit juice 34","sugar":195.00311,"criteria":252}, + {"name":"Fruit juice 37","sugar":100.18925,"criteria":133}, + {"name":"Fruit juice 53","sugar":154.46834,"criteria":180}, + {"name":"Tea 23","sugar":153.91217,"criteria":175}, + {"name":"Tea 71","sugar":192.72974,"criteria":203}, + {"name":"Tea 98","sugar":138.71013,"criteria":162}, + {"name":"Candy 8","sugar":149.59752,"criteria":160}, + {"name":"Candy 14","sugar":183.19849,"criteria":242}, + {"name":"Chocolate 16","sugar":130.96481,"criteria":165}, + {"name":"Smoothie 18","sugar":166.2304,"criteria":193}, + {"name":"Smoothie 73","sugar":132.69725,"criteria":151}, + {"name":"Apple 73","sugar":160.8539,"criteria":207}, + {"name":"Fruit juice 20","sugar":122.614525,"criteria":177}, + {"name":"Cake 12","sugar":182.76157,"criteria":236}, + {"name":"Chocolate 0","sugar":146.81622,"criteria":206}, + {"name":"Apple 99","sugar":182.31323,"criteria":211}, + {"name":"Candy 49","sugar":136.16162,"criteria":193}, + {"name":"Chocolate 56","sugar":128.53404,"criteria":145}, + {"name":"Fruit juice 44","sugar":177.52731,"criteria":217}, + {"name":"Ice cream 78","sugar":112.97374,"criteria":146}, + {"name":"Cake 42","sugar":107.52386,"criteria":123}, + {"name":"Cake 99","sugar":137.5299,"criteria":185}, + {"name":"Apple 48","sugar":194.78995,"criteria":231}, + {"name":"Fruit juice 61","sugar":109.11185,"criteria":138}, + {"name":"Chocolate 41","sugar":136.47095,"criteria":185}, + {"name":"Tea 95","sugar":133.09335,"criteria":179}, + {"name":"Fruit juice 59","sugar":168.67265,"criteria":208}, + {"name":"Candy 21","sugar":125.954384,"criteria":139}, + {"name":"Fruit juice 33","sugar":146.21214,"criteria":183}, + {"name":"Candy 48","sugar":196.9039,"criteria":249}, + {"name":"Tea 8","sugar":171.0748,"criteria":193}, + {"name":"Smoothie 74","sugar":111.57121,"criteria":124}, + {"name":"Apple 91","sugar":169.62463,"criteria":201}, + {"name":"Cake 12","sugar":115.3386,"criteria":173}, + {"name":"Fruit juice 62","sugar":174.87453,"criteria":226}, + {"name":"Fruit juice 60","sugar":152.54874,"criteria":175}, + {"name":"Apple 56","sugar":165.61108,"criteria":213}, + {"name":"Candy 3","sugar":136.42447,"criteria":175} +] \ No newline at end of file diff --git a/ruby-egzas/README.md b/ruby-egzas/README.md new file mode 100644 index 0000000..ad46e5f --- /dev/null +++ b/ruby-egzas/README.md @@ -0,0 +1,3 @@ +```shell +ruby main.rb +``` diff --git a/ruby-egzas/main.rb b/ruby-egzas/main.rb new file mode 100644 index 0000000..84271d6 --- /dev/null +++ b/ruby-egzas/main.rb @@ -0,0 +1,220 @@ +require "json" +$VERBOSE = nil # Suppress verbose warnings + +# Define a class for data entries +class DataEntry + attr_reader :name + attr_reader :sugar + attr_reader :criteria + + def initialize(name, sugar, criteria) + @name = name + @sugar = sugar + @criteria = criteria + end + + def to_s + "#" + end +end + +# Define a class for result entries +class ResultEntry + attr_reader :name + attr_reader :sugar + + def initialize(name, sugar) + @name = name + @sugar = sugar + end + + def to_s + "#" + end +end + +# Define a class for input messages +class InputMessage + attr_reader :data + + def initialize(data) + @data = data + end +end + +# Define a class for result messages +class ResultMessage + attr_reader :tid + attr_reader :data + + def initialize(tid, data) + @tid = tid + @data = data + end +end + +# Define a class for finished messages +class FinishedMessage + attr_reader :tid + + def initialize(tid) + @tid = tid + end +end + +# Define a class for final results messages +class FinalResultsMessage + attr_reader :data + + def initialize(data) + @data = data + end +end + +# Method to read data from a file and convert it to DataEntry objects +def read_data(file_path) + data = [] + json_data = File.read(file_path) + JSON.parse(json_data).each do |entry| + data.push(DataEntry.new(entry["name"], entry["sugar"].to_f, entry["criteria"].to_i)) + end + return data +end + +# Constants +worker_count = 12 +data = read_data("IF-1-1_PuzonasR_dat_1.json") +results_path = "results.txt" +logs_path = "logs.txt" + +# Method to process data and return a ResultMessage or FinishedMessage +def process_data(tid, data_entry) + if data_entry.sugar > data_entry.criteria + sleep 0.25 + ResultMessage.new(tid, ResultEntry.new(data_entry.name, data_entry.sugar)) + else + FinishedMessage.new(tid) + end +end + +# Create Ractors for workers +workers = Array.new(worker_count) do |index| + Ractor.new(index) do |index| + distributer = Ractor.receive + + loop do + data_entry = Ractor.receive + if data_entry == nil then break end + + distributer.send(process_data(index, data_entry)) + end + end +end + +# Create Ractors for result collector, results writer, and logger +result_collector = Ractor.new do + results = [] + distributer = Ractor.receive + + loop do + result = Ractor.receive + if result == nil then break end + + index = results.index { |old_value| old_value.sugar > result.sugar } + if index then + results.insert(index, result) + else + results.push(result) + end + end + + distributer.send(FinalResultsMessage.new(results)) +end + +results_writer = Ractor.new(results_path) do |results_path| + results = Ractor.receive + File.open(results_path, "w") do |file| + file.puts "--------------------------------" + file.puts "| %-15s | %-10s |" % ["Name", "Sugar"] + file.puts "--------------------------------" + results.each do |result| + file.puts "| %-15s | %-10s |" % [result.name, result.sugar] + end + file.puts "--------------------------------" + end +end + +logger = Ractor.new(logs_path) do |logs_path| + File.open(logs_path, "w") do |file| + loop do + msg = Ractor.receive + if msg == nil then break end + file.puts msg + end + end +end + +# Create a distributer Ractor to manage communication between other Ractors +distributer = Ractor.new(logger, result_collector, results_writer, workers, worker_count) do |logger, result_collector, results_writer, workers, worker_count| + workers.each do |worker| + worker.send(Ractor.current) + end + result_collector.send(Ractor.current) + + worker_counter = 0 + input_counter = 0 + result_counter = 0 + + workers_active = true + + loop do + msg = Ractor.receive + if msg == nil then break end + + if workers_active and msg.is_a?(InputMessage) then + tid = input_counter % worker_count + logger.send("[ ->worker#{tid.to_s.ljust(2)} ] Input message, data: #{msg.data}") + workers[tid].send(msg.data) + input_counter += 1 + elsif workers_active and msg.is_a?(ResultMessage) then + logger.send("[worker#{msg.tid.to_s.ljust(2)} ->result_collector] Result message, data: #{msg.data}") + result_counter += 1 + result_collector.send(msg.data) + elsif workers_active and msg.is_a?(FinishedMessage) then + logger.send("[worker#{msg.tid.to_s.ljust(2)} -> ] Finished message") + result_counter += 1 + elsif msg.is_a?(FinalResultsMessage) then + logger.send("[result_collector->result_writer ] Writing results to file") + results_writer.send(msg.data) + else + logger.send("[ -> ] Unknown message") + end + + if input_counter == result_counter then + logger.send("[ ->result_collector] Stop message") + result_collector.send(nil) + workers.each_with_index do |worker, tid| + logger.send("[ ->worker#{tid.to_s.ljust(2)} ] Stop message") + worker.send(nil) + end + end + end + + logger.send("[ ->logger ] Stop message") + logger.send(nil) +end + +# Send input messages to the distributer +data.each do |data_entry| + distributer.send(InputMessage.new(data_entry)) +end + +# Finalize Ractors by sending stop messages and collecting results +distributer.take +workers.each(&:take) +result_collector.take +results_writer.take +logger.take + +# when 'worker_count = 1' , time taken: 10.058 +# when 'worker_count = 12', time taken: 1.055