loganmeetsworld/kiq

View on GitHub
lib/kiq/run.rb

Summary

Maintainability
A
35 mins
Test Coverage
require 'yaml'
require 'kiq/project'
require 'kiq/backer'
require 'kiq/helpers/constants'
require 'kiq/helpers/display'

module Kiq
  FILE = File.expand_path('.kiq')
  module CLI
    # Runs the program when the user types 'kiq'
    class Run
      # Initialize the Run with a projects hash and load the file
      def initialize
        @projects = {}
        load_file
        load_projects
      end

      # Uses user input
      # @return [String] help documentation or handles valid input
      def perform
        user_input      = ARGV
        primary_command = user_input[0]
        valid_commands  = ['project', 'list', 'back', 'backer']

        case primary_command
        when *valid_commands
          handle(user_input)
        when '-v'
          puts Kiq::VERSION
        when nil
          Display.help
        when '--help'
          Display.help
        else
          puts "Unknown command: '#{user_input}'." unless user_input == '-h'
          Display.help
        end
      end

      # Handles valid input
      # Runs relevant method for command
      # Returns help if user input indicates help is needed
      def handle(input)
        if input[-1] == '--help'
          return Display.command_help(input[0])
        end

        case input[0]
        when "project"
          add(input)
        when "back"
          back(input[0], input[1], input[2], input[3], input[4])
        when "list"
          list(input[1])
        when "backer"
          backer(input[1])
        end
      end

      # @param project [Array]
      # Returns successful message if project added
      # Returns help if add is unsuccessful
      def add(project)
        type = project[0]
        name = project[1]
        amount = project[2]

        if Project.validate_project(project, @projects)
          @projects[name] = Project.new(name, amount)
          save
          puts "Added Project: #{name}!"
        else
          Display.command_help(type)
        end
      end

      # @param type [String]
      # @param backer_name [String]
      # @param project_name [String]
      # @param credit_card [String]
      # @param amount [String]
      # @return [String] successful message if user input is valid, help if back is unsuccessful
      def back(type, backer_name, project_name, credit_card, amount)
        project = @projects[project_name]
        if Backer.validate_project_exists(project) && Backer.validate_card(project, credit_card) && Backer.validate_backer_name(backer_name) && Backer.check_amount_dollar_sign(amount)
          backer = Backer.new(backer_name, credit_card, amount)
          project.backers[credit_card] = backer
          update_goal(project, amount)
          save
          puts "#{backer.name.capitalize} backed #{project_name} for $#{backer.amount}."
        else
          Display.command_help(type)
        end
      end

      # @param project_name [String]
      # If Project instance exists, lists all backers for a certain project
      # @return [String] of backers, or error and help if project does not exist
      def list(project_name)
        if !Project.project_does_not_exist?(['project', project_name], @projects)
          project = Project.all_offspring.find { |p| p.name == project_name }
          puts "Project Name: #{project.name}"
          puts "Amount Remaining: $#{project.amount}"
          check_goal(project)
          puts "BACKERS:"
          project.backers.each do |backer|
            puts "Backer #{backer[1].name}, Amount: $#{backer[1].amount}"
          end
        else
          puts "ERROR: Project does not exist.\n\n"
          Display.help
        end
      end

      # @param backer_name [String]
      # Lists projects backed by a certain backer
      # @return [String] of projects, or nothing if none exist
      def backer(backer_name)
        @projects.each do |project|
          project[1].backers.each do |backer|
            if backer[1].name == backer_name
              puts "Backed #{project[1].name} for $#{backer[1].amount} dollars"
            end
          end
        end
      end

      private

      # Accessor for the project list file
      # Returns the file path
      def file
        @file ||= File.exist?(FILE) ? FILE : '.kiq'
      end

      # Creates a new project file if none exists
      # Returns nothing
      def load_file
        File.exist?(file) ? return : save
      end

      # Loads the yaml projects file and creates a projects hash
      # Returns nothing
      def load_projects
        unless File.zero?(@file)
          contents = YAML.load_file(@file)
          contents.keys.each do |d|
            @projects[d] = Project.new(contents[d].name, contents[d].amount, contents[d].backers)
          end
        end
      end

      # Saves the current list of projects to the yaml file (serialization)
      # Returns nothing
      def save
        File.open(file, "w") {|f| f.write(@projects.to_yaml) }
      end

      # Updates project goal
      # Returns check_goal if goal is met
      def update_goal(project, amount)
        project.amount = project.amount.to_f - amount.to_f
        check_goal(project)
      end

      # Checks if project amount has met the goal
      # @return [String] success message if goal met, else returns nothing
      def check_goal(project)
        if project.amount.to_i <= 0
          puts "Reached goal!"
        end
      end
    end
  end
end