MST

星途 面试题库

面试题:Ruby实时数据处理与简单可视化结合

使用Ruby和一个常用的可视化库(如Gosu或Chartkick,任选其一),实现一个简单的实时图表。实时数据通过一个不断更新的文本文件获取,文本文件每行一个数字。要求在图表中实时绘制这些数字的变化曲线,并且当新数据到达时,图表能平滑更新。
26.2万 热度难度
编程语言Ruby

知识考点

AI 面试

面试题答案

一键面试

使用Gosu实现实时图表

  1. 安装依赖: 确保安装了gosu库,可以通过gem install gosu进行安装。

  2. Ruby代码实现

require 'gosu'

class RealTimeChart < Gosu::Window
  def initialize
    super(800, 600, false)
    self.caption = 'Real - Time Chart'
    @data = []
    @font = Gosu::Font.new(self, Gosu::default_font_name, 20)
    @last_update_time = 0
  end

  def update
    new_data = load_data
    @data.concat(new_data) if new_data.any?
    @data = @data[-100..-1] if @data.length > 100
  end

  def draw
    draw_background
    draw_axis
    draw_chart
  end

  private

  def load_data
    new_data = []
    if File.exist?('data.txt')
      File.foreach('data.txt') do |line|
        new_data << line.chomp.to_f
      end
      File.write('data.txt', '')
    end
    new_data
  end

  def draw_background
    Gosu.draw_rect(0, 0, width, height, Gosu::Color::WHITE)
  end

  def draw_axis
    Gosu.draw_line(50, height - 50, 50, 50, Gosu::Color::BLACK)
    Gosu.draw_line(50, height - 50, width - 50, height - 50, Gosu::Color::BLACK)
    @font.draw('X', width - 40, height - 40, 1, 1, 1, Gosu::Color::BLACK)
    @font.draw('Y', 40, 40, 1, 1, 1, Gosu::Color::BLACK)
  end

  def draw_chart
    return if @data.empty?
    max_value = @data.max
    min_value = @data.min
    data_points = @data.map.with_index do |value, index|
      x = 50 + (index * (width - 100) / (@data.length - 1))
      y = height - 50 - ((value - min_value) * (height - 100) / (max_value - min_value))
      [x, y]
    end
    (0...data_points.length - 1).each do |i|
      Gosu.draw_line(data_points[i][0], data_points[i][1], data_points[i + 1][0], data_points[i + 1][1], Gosu::Color::BLUE)
    end
  end
end

window = RealTimeChart.new
window.show

使用Chartkick实现实时图表

  1. 安装依赖: 确保安装了chartkicksinatra库,可以通过gem install chartkick sinatra进行安装。

  2. Ruby代码实现

require'sinatra'
require 'chartkick'
require 'json'

enable :sessions

get '/' do
  erb :index
end

post '/update' do
  new_data = []
  if File.exist?('data.txt')
    File.foreach('data.txt') do |line|
      new_data << line.chomp.to_f
    end
    File.write('data.txt', '')
  end
  session[:data] ||= []
  session[:data].concat(new_data)
  session[:data] = session[:data][-100..-1] if session[:data].length > 100
  content_type :json
  { data: session[:data] }.to_json
end
  1. HTML和JavaScript实现(views/index.erb
<!DOCTYPE html>
<html>

<head>
  <title>Real - Time Chart</title>
  <script src="https://www.gstatic.com/charts/loader.js"></script>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script>
    google.charts.load('current', { 'packages': ['corechart'] });
    google.charts.setOnLoadCallback(drawChart);

    function drawChart() {
      var data = new google.visualization.DataTable();
      data.addColumn('number', 'Index');
      data.addColumn('number', 'Value');
      var options = {
        title: 'Real - Time Chart',
        curveType: 'function',
        legend: { position: 'bottom' }
      };
      var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
      function updateChart() {
        $.post('/update', function (result) {
          data.removeRows(0, data.getNumberOfRows());
          result.data.forEach(function (value, index) {
            data.addRow([index, value]);
          });
          chart.draw(data, options);
        });
      }
      setInterval(updateChart, 1000);
      updateChart();
    }
  </script>
</head>

<body>
  <div id="chart_div" style="width: 800px; height: 600px;"></div>
</body>

</html>

上述代码中,Gosu实现通过直接绘制图形来展示实时图表;Chartkick结合Sinatra实现了一个Web应用,通过AJAX请求更新图表数据。在实际运行时,确保有一个不断写入数字到data.txt的进程。