<commit_before># port of testdroid's device_finder.py
# https://raw.githubusercontent.com/bitbar/testdroid-samples/03fc043ba98235b9ea46a0ab8646f3b20dd1960e/appium/sample-scripts/python/device_finder.py

require 'rubygems'
require 'rest-client'
require 'json'

# RestClient.log = 'stdout'

class DeviceFinder
  # Cloud URL (not including API path)
  attr_accessor :cloud_url
  # Oauth access token
  attr_accessor :access_token
  # Oauth refresh token
  attr_accessor :refresh_token
  # Unix timestamp (seconds) when token expires
  attr_accessor :token_expiration_time
  # Testdroid username
  attr_accessor :username
  # Testdroid password
  attr_accessor :password

  # Full constructor with username and password

  def initialize username, password, url='https://cloud.testdroid.com'
    @username  = username
    @password  = password
    @cloud_url = url
  end

  # Get Oauth2 token
  def get_token
    if not access_token
      # TODO: refresh
      url     = "#{cloud_url}/oauth/token"
      payload = {
        'client_id':  'testdroid-cloud-api',
        'grant_type': 'password',
        'username':   username,
        'password':   password
      }

      res = RestClient.post(url,
                            payload,
                            content_type: :json,
                            accept:       :json)
      if res.code != 200
        puts 'FAILED: Authentication or connection failure. Check Testdroid Cloud URL and your credentials.'
        exit -1
      end

      reply = JSON.parse(res)

      @access_token          = reply['access_token']
      @refresh_token         = reply['refresh_token']
      @token_expiration_time = Time.now + reply['expires_in']
    elsif token_expiration_time < Time.now
      url     = "#{cloud_url}/oauth/token"
      payload = {
        'client_id':     'testdroid-cloud-api',
        'grant_type':    'refresh_token',
        'refresh_token': refresh_token
      }
      res     = RestClient.post(url,
                                payload,
                                content_type: :json,
                                accept:       :json)
      if res.code != 200
        puts 'FAILED: Unable to get a new access token using refresh token'
        @access_token = nil
        return get_token
      end

      reply = JSON.parse(res)

      @access_token          = reply['access_token']
      @refresh_token         = reply['refresh_token']
      @token_expiration_time = Time.now + reply['expires_in']
    end

    access_token
  end

  # Helper method for getting necessary headers to use for API calls, including authentication
  def _build_headers
    { Authorization: "Bearer #{get_token}", content_type: :json, accept: :json }
  end

  # GET from API resource
  def get path=nil, headers={}
    if (path.index('v2/') || -1) >= 0
      cut_path = path.split('v2/')
      path     = cut_path[1]
    end

    url = "#{cloud_url}/api/v2/#{path}"
    headers.merge!(_build_headers)
    res = RestClient.get url, headers

    if res.headers[:content_type].include? 'application/json'
      JSON.parse(res)
    else
      res.body
    end
  end

  # Returns list of devices
  def get_devices limit=0
    get "devices?limit=#{limit}"
  end

  # Find available free Android device
  def available_free_android_device limit=0
    puts 'Searching Available Free Android Device...'

    get_devices(limit)['data'].each do |device|
      if device['creditsPrice'] == 0 and
        device['locked'] == false and
        device['osType'] == 'ANDROID' and
        device['softwareVersion']['apiLevel'] > 16

        puts "Found device #{device['displayName']}"
        puts
        return device['displayName']
      end
    end

    puts 'No available device found'
    puts
  end
<commit_msg>Select Android devices based on RAM<commit_after># port of testdroid's device_finder.py
# https://raw.githubusercontent.com/bitbar/testdroid-samples/03fc043ba98235b9ea46a0ab8646f3b20dd1960e/appium/sample-scripts/python/device_finder.py

require 'rubygems'
require 'rest-client'
require 'json'

# RestClient.log = 'stdout'

class DeviceFinder
  # Cloud URL (not including API path)
  attr_accessor :cloud_url
  # Oauth access token
  attr_accessor :access_token
  # Oauth refresh token
  attr_accessor :refresh_token
  # Unix timestamp (seconds) when token expires
  attr_accessor :token_expiration_time
  # Testdroid username
  attr_accessor :username
  # Testdroid password
  attr_accessor :password

  # Full constructor with username and password

  def initialize username, password, url='https://cloud.testdroid.com'
    @username  = username
    @password  = password
    @cloud_url = url
  end

  # Get Oauth2 token
  def get_token
    if not access_token
      # TODO: refresh
      url     = "#{cloud_url}/oauth/token"
      payload = {
        'client_id':  'testdroid-cloud-api',
        'grant_type': 'password',
        'username':   username,
        'password':   password
      }

      res = RestClient.post(url,
                            payload,
                            content_type: :json,
                            accept:       :json)
      if res.code != 200
        puts 'FAILED: Authentication or connection failure. Check Testdroid Cloud URL and your credentials.'
        exit -1
      end

      reply = JSON.parse(res)

      @access_token          = reply['access_token']
      @refresh_token         = reply['refresh_token']
      @token_expiration_time = Time.now + reply['expires_in']
    elsif token_expiration_time < Time.now
      url     = "#{cloud_url}/oauth/token"
      payload = {
        'client_id':     'testdroid-cloud-api',
        'grant_type':    'refresh_token',
        'refresh_token': refresh_token
      }
      res     = RestClient.post(url,
                                payload,
                                content_type: :json,
                                accept:       :json)
      if res.code != 200
        puts 'FAILED: Unable to get a new access token using refresh token'
        @access_token = nil
        return get_token
      end

      reply = JSON.parse(res)

      @access_token          = reply['access_token']
      @refresh_token         = reply['refresh_token']
      @token_expiration_time = Time.now + reply['expires_in']
    end

    access_token
  end

  # Helper method for getting necessary headers to use for API calls, including authentication
  def _build_headers
    { Authorization: "Bearer #{get_token}", content_type: :json, accept: :json }
  end

  # GET from API resource
  def get path=nil, headers={}
    if (path.index('v2/') || -1) >= 0
      cut_path = path.split('v2/')
      path     = cut_path[1]
    end

    url = "#{cloud_url}/api/v2/#{path}"
    headers.merge!(_build_headers)
    res = RestClient.get url, headers

    if res.headers[:content_type].include? 'application/json'
      JSON.parse(res)
    else
      res.body
    end
  end

  # Returns list of devices
  def get_devices limit=0
    get "devices?limit=#{limit}"
  end

  # Returns device properties (ram, screen size, etc.)
  def get_device_properties device_id
    get "devices/#{device_id}/properties"
  end

  # Returns device ram in megabytes
  def get_device_ram device_id
    data = get_device_properties(device_id)['data']
    data.detect { |obj| obj['id'] == 118305 }['name'].gsub(/\D/,'').to_i
  end

  # Find available free Android device
  def available_free_android_device limit=0
    puts 'Searching Available Free Android Device...'

    get_devices(limit)['data'].each do |device|
      if device['creditsPrice'] == 0 and
        device['locked'] == false and
        device['osType'] == 'ANDROID' and
        device['softwareVersion']['apiLevel'] > 16

        ram = get_device_ram device['id']
        next if ram < 1024

        puts "Found device #{device['displayName']}"
        puts
        return device['displayName']
      end
    end

    puts 'No available device found'
    puts
  end

{'fraction_non_alphanumeric': 0.09825354944088453, 'fraction_numerical': 0.012313104661389622, 'mean_word_length': 2.368599238256454, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 7, 'https://': 4, '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': '7509662', 'n_tokens_mistral': 2449, 'n_tokens_neox': 2352, 'n_words': 611}