CLOUDACCESSID="<Your Cloud Access Code>"
CLOUDKEY="<Your Cloud Secret Key>"
CLOUDPOOL="<Your Pool Name>"

print("#################################################################################")
print("                       Cloud REST API Sample")
from gurobipy import * 
import requests 
import json
import time
import sys

env = None
model = None

try:
    # curl -X POST "https://cloud.gurobi.com/api/v2/pools/<pool name>/machines" -H  "accept: application/json" -H  
    # "X-GUROBI-ACCESS-ID: <access code> -H  "X-GUROBI-SECRET-KEY: <secret key>"
    urlCloud = 'https://cloud.gurobi.com/api/v2/'

    print("1. Make sure the Cloud Pool is started...")
    response = requests.post(urlCloud + 'pools/' + CLOUDPOOL + '/machines'
                            , headers={ 'Content-Type':'application/json'
                            , 'Accept':'application/json'
                            , 'X-GUROBI-ACCESS-ID': CLOUDACCESSID
                            ,'X-GUROBI-SECRET-KEY': CLOUDKEY})


    print("2. TODO: Run code to prepare your data here ...")
    categories, minNutrition, maxNutrition = multidict({
    'calories': [1800, 2200],
    'protein':  [91, GRB.INFINITY],
    'fat':      [0, 65],
    'sodium':   [0, 1779] })
    foods, cost = multidict({
    'hamburger': 2.49,
    'chicken':   2.89,
    'hot dog':   1.50,
    'fries':     1.89,
    'macaroni':  2.09,
    'pizza':     1.99,
    'salad':     2.49,
    'milk':      0.89,
    'ice cream': 1.59 })
    # Nutrition values for the foods
    nutritionValues = {
    ('hamburger', 'calories'): 410,
    ('hamburger', 'protein'):  24,
    ('hamburger', 'fat'):      26,
    ('hamburger', 'sodium'):   730,
    ('chicken',   'calories'): 420,
    ('chicken',   'protein'):  32,
    ('chicken',   'fat'):      10,
    ('chicken',   'sodium'):   1190,
    ('hot dog',   'calories'): 560,
    ('hot dog',   'protein'):  20,
    ('hot dog',   'fat'):      32,
    ('hot dog',   'sodium'):   1800,
    ('fries',     'calories'): 380,
    ('fries',     'protein'):  4,
    ('fries',     'fat'):      19,
    ('fries',     'sodium'):   270,
    ('macaroni',  'calories'): 320,
    ('macaroni',  'protein'):  12,
    ('macaroni',  'fat'):      10,
    ('macaroni',  'sodium'):   930,
    ('pizza',     'calories'): 320,
    ('pizza',     'protein'):  15,
    ('pizza',     'fat'):      12,
    ('pizza',     'sodium'):   820,
    ('salad',     'calories'): 320,
    ('salad',     'protein'):  31,
    ('salad',     'fat'):      12,
    ('salad',     'sodium'):   1230,
    ('milk',      'calories'): 100,
    ('milk',      'protein'):  8,
    ('milk',      'fat'):      2.5,
    ('milk',      'sodium'):   125,
    ('ice cream', 'calories'): 330,
    ('ice cream', 'protein'):  8,
    ('ice cream', 'fat'):      10,
    ('ice cream', 'sodium'):   180 }

    # Return a boolean thatis true when the server is ready:
    def waitForPoolReady():
        ctr = 0
        bReady = False
        while ctr < 120 and bReady == False:
            time.sleep(1)
            ctr = ctr + 1  # <-- Avoid looping forever, just to be safe
            response = requests.get(urlCloud + 'pools/' + CLOUDPOOL + '/machines'
                                    , headers={ 'Content-Type':'application/json'
                                    , 'Accept':'application/json'
                                    , 'X-GUROBI-ACCESS-ID': CLOUDACCESSID
                                    , 'X-GUROBI-SECRET-KEY':  CLOUDKEY})
            if response.status_code == 200:
                state = ""
                serverInfo = json.loads(response.content)
                try:
                    state = serverInfo["computeServers"][0]["state"]
                    print("   state = " + state)
                    if state == "running" or state == "idle":
                        bReady = True
                except Exception as e:
                    break;
            else:
                break;
        return bReady

    bReady = False
    if response.status_code == 200 :
        bReady = True
        print("   pool is ready ... ")
    else:
        if response.status_code == 202 :
            print("   pool is starting ... ")
            #########
            # You can  this step. Then the following Env call will block until the pool is running. 
            bReady = waitForPoolReady()
            #########
        else:
            print("   error starting pool. Error status returned from post request.")
            sys.exit(-1)

    if bReady != True:
        print("   failed to start pool.")
        sys.exit(-1)

    print("3. Define the model:")
    env = Env.CloudEnv("some.log", CLOUDACCESSID, CLOUDKEY, pool=CLOUDPOOL) 
    model = Model("diet")
    buy = model.addVars(foods, name="buy")
    model.setObjective(buy.prod(cost), GRB.MINIMIZE)
    model.addConstrs(   
        (quicksum(nutritionValues[f,c] * buy[f] for f in foods)
            == [minNutrition[c], maxNutrition[c]]
        for c in categories), "_")
    jobid = model.getAttr("JobID")
    print("   The ID for this job is " + jobid)
    print("4. Solve the model:")
    model.optimize()
    print("5. TODO: Do something with the solution here.")

except Exception as e:
    print('Error reported')

finally:
    if model != None:
        del model
    if env != None:
        del env

print("All done.")
