<commit_before># Contains Server Code
require "highline/import"
require "socket"

class Server
  
  # Used to initialize server variables 
  def initialize( port, ip )
  	# Used to open the TCP socket on the given port
    @server = TCPServer.open( ip, port )
    
    # Contains details of users connected to the server.
    @users = Hash.new

    # Game data
    @score = Hash.new
    @public_ciphers = []
    
    run
  end

  # Used to parse messages incoming to the server. Takes appropriate action.
  def parse_message(message, username)
  	if message.include? 'scoreboard'
  		  
      s_b = ""
      s_b += "************************************************\n"

      temp_score = @score
      temp_score.sort_by {|key, value| value}.reverse

      # Needs to be beautified.
      temp_score.each do |team, current_score|
        s_b += "#{team}: #{current_score}\n"
      end

      s_b += "************************************************\n\n\0"
      return s_b
  	
    elsif message.include? 'plain->' and message.include? 'cipher->' and message.include? 'comment->'

      data = []

  		# The following code segment is used to extract plaintext, ciphertext and comment
  		message.split(',').each do |str|
  			data.push str.split('->')[1]
  		end

      # new_cipher is used to store cipher-related data.

      new_cipher = Hash.new

      new_cipher[:plain]   = data[0]
      new_cipher[:cipher]  = data[1]
      new_cipher[:comment] = data[2]

      team_name = @users[username][:team]
      new_cipher[:team] = team_name

      # Adds the new cipher to the existing list
  		@public_ciphers.push new_cipher

      # Reduce team score for publishing a cipher by 5
      @score[team_name] -= 5
      
      pub = ""
      pub += "*************************************************\n"
      pub += "Published.\n"
      pub += "*************************************************\n\0"

      return pub

  	elsif message.include? 'listing'
      
      # Needs beautification
      c_l = ""
      c_l += "*************************************************\n"
      # Variable for indexing into the cipher array
      count=1

      @public_ciphers.each do |c_hash|
        c_l += "#{count}. Ciphetext: #{c_hash[:cipher]}, Comment: #{c_hash[:comment]}, Team: #{c_hash[:team]}\n"
        count+=1
      end

      c_l += "*************************************************\n\n\0"

      # Returns list of all ciphers with team name and comment
      return c_l
    
    elsif message.include? 'solve'

      # Split message to get all fields
      solve, number, text = message.split(':')
      
      # Cipher the user wants to solve
      cipher = @public_ciphers[(number.to_i)-1]
      team_name = @users[username][:team]

      if cipher[:plain] == text and cipher[:team] == team_name
        @score[team_name] += 10
        return "Solved your own cipher!\0"
      
      elsif cipher[:plain] == text and cipher[:team] != team_name
        @score[team_name] += 2
        @score[cipher[:team]] -= 1
        return "Solved other teams' cipher.\0"
      
      else
        return "Wrong submission\0"
      end

    end
  end

  # Used to fork a thread for every new connection.
  def run
    loop {
      Thread.start(@server.accept) do | client |
        type, t_name, u_name = client.gets.chomp.split(':')

        if t_name == nil or u_name == nil or type == nil
          client.puts "Invalid: Login.\0"
          Thread.kill self
        end

        @users.each do |username, details|
          if username == u_name
            client.puts "Invalid: This username already exists.\0"
            Thread.kill self
          elsif details[:team] == t_name and details[:type] == type<commit_msg>Reads and writes scoreboard as JSON to a file<commit_after># Contains Server Code
require "highline/import"
require "socket"
require "json"

class Server
  
  # Used to initialize server variables 
  def initialize( port, ip )
  	# Used to open the TCP socket on the given port
    @server = TCPServer.open( ip, port )
    
    # Contains details of users connected to the server.
    @users = Hash.new

    # Game data
    @score = Hash.new
    @score = JSON.parse(File.read("../save_data/score.json"))
    @public_ciphers = []
    
    run
  end

  # Writes score to file, just in case the server goes down duting game time.
  def write_score
    File.open("../save_data/score.json", "w") do |f|
        f.write(@score.to_json)
    end
  end

  # Used to parse messages incoming to the server. Takes appropriate action.
  def parse_message(message, username)
    if message.include? 'scoreboard'
  		  
      s_b = ""
      s_b += "************************************************\n"

      temp_score = @score
      temp_score.sort_by {|key, value| value}.reverse

      # Needs to be beautified.
      temp_score.each do |team, current_score|
        s_b += "#{team}: #{current_score}\n"
      end

      s_b += "************************************************\n\n\0"
      return s_b
  	
    elsif message.include? 'plain->' and message.include? 'cipher->' and message.include? 'comment->'

      data = []

  		# The following code segment is used to extract plaintext, ciphertext and comment
  		message.split(',').each do |str|
  			data.push str.split('->')[1]
  		end

      # new_cipher is used to store cipher-related data.

      new_cipher = Hash.new

      new_cipher[:plain]   = data[0]
      new_cipher[:cipher]  = data[1]
      new_cipher[:comment] = data[2]

      team_name = @users[username][:team]
      new_cipher[:team] = team_name

      # Adds the new cipher to the existing list
  		@public_ciphers.push new_cipher

      # Reduce team score for publishing a cipher by 5
      @score[team_name] -= 5
      write_score
      
      pub = ""
      pub += "*************************************************\n"
      pub += "Published.\n"
      pub += "*************************************************\n\0"

      return pub

  	elsif message.include? 'listing'
      
      # Needs beautification
      c_l = ""
      c_l += "*************************************************\n"
      # Variable for indexing into the cipher array
      count=1

      @public_ciphers.each do |c_hash|
        c_l += "#{count}. Ciphetext: #{c_hash[:cipher]}, Comment: #{c_hash[:comment]}, Team: #{c_hash[:team]}\n"
        count+=1
      end

      c_l += "*************************************************\n\n\0"

      # Returns list of all ciphers with team name and comment
      return c_l
    
    elsif message.include? 'solve'

      # Split message to get all fields
      message = message.split(":")
      number, text = message[1], message[2]
      
      # Cipher the user wants to solve
      cipher = @public_ciphers[(number.to_i)-1]
      team_name = @users[username][:team]

      if cipher[:plain] == text and cipher[:team] == team_name
        @score[team_name] += 10
        write_score
        return "Solved your own cipher!\0"
      
      elsif cipher[:plain] == text and cipher[:team] != team_name
        @score[team_name] += 2
        @score[cipher[:team]] -= 1
        return "Solved other teams' cipher.\0"
      
      else
        return "Wrong submission\0"
      end

    end
  end

  # Used to fork a thread for every new connection.
  def run
    loop {
      Thread.start(@server.accept) do | client |
        type, t_name, u_name = client.gets.chomp.split(':')

        if t_name == nil or u_name == nil or type == nil
          client.puts "Invalid: Login.\0"
          Thread.kill self
        end

        @users.each do |username, details|
          if username == u_name
            client.puts "Invalid: This username already exists.\0"
            Thread.kill self
          elsif details[:team] == t_name and details[:type] == type
{'fraction_non_alphanumeric': 0.18052347959969206, 'fraction_numerical': 0.0056453682319733125, 'mean_word_length': 2.429388473383194, 'pattern_counts': {'":': 1, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1945059', 'n_tokens_mistral': 2435, 'n_tokens_neox': 2292, 'n_words': 688}