Skip to content

Commit

Permalink
Merge branch 'master' of github.com:battlecode/battlecode20
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mao committed Jan 16, 2020
2 parents 64e6785 + ecbf605 commit 457f9c2
Show file tree
Hide file tree
Showing 40 changed files with 895 additions and 293 deletions.
16 changes: 15 additions & 1 deletion backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ Always commit the most recent `requirements.txt`.

## Deployment

#### Steps

1. Push to master.
2. Go to [Cloud Build Triggers](https://console.cloud.google.com/cloud-build/triggers?project=battlecode18) on Google Cloud.
3. Click "Run trigger" under the `battlecode/battlecode20` trigger.
4. Go to [Cloud Build History](https://console.cloud.google.com/cloud-build/builds?project=battlecode18). You should see a spinning blue icon next to a recently started build, which should reference the most recent commit ID on master on this repo. Wait until the spinning icon turns into a green checkmark (this usually takes 2-3 minutes).
5. Go to the [battlecode20-backend-true](https://console.cloud.google.com/compute/instanceGroups/details/us-east1-b/battlecode20-backend-true?project=battlecode18) instance group in the Compute Engine. Press `Rolling Restart/Replace`.
6. Change operation from `Restart` to `Replace`. Let maximum surge be 1 and **maximum unavailable be 0** (we don't want our server to go down).
7. Wait until all spinning blue icons have turned into green checkmarks (this takes like 10 minutes I think).

This procedure is currently very long and requires too much manual intervention. We should write a script that does all of this for us (which shouldn't be too hard).

#### Setup

A database should be created.

We currently have continuous builds triggered by pushes to master. Therefore, make sure that everything is actually working before pushing. Also, make sure that any new database migrations are also applied to the production server before deploying. A good way to ensure this is to always test locally with the production database, before committing and pushing to master.
Expand All @@ -94,4 +108,4 @@ The images are then deployed as an instance group on GCE. To update the instance

Pls pls use SHA256 digests in the `Dockerfile`. Otherwise, the image might be rebuilt, from the same commit tag as before, but not working anymore (this happened, and it was not fun).

Ideally, we would like to move to Kubernetes for everything, as that would make everything much easier, but it doesn't currently support having a load balancer that also points to storage buckets. This is a deal-breaker, since the frontend is static.
Ideally, we would like to move to Kubernetes for everything, as that would make everything much easier, but it doesn't currently support having a load balancer that also points to storage buckets. This is a deal-breaker, since the frontend is static.
71 changes: 40 additions & 31 deletions backend/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,39 +42,48 @@ def callback(api_future):
raise
return callback

def pub(project_id, topic_name, data=""):
def pub(project_id, topic_name, data="", num_retries=5):
"""Publishes a message to a Pub/Sub topic."""

# Initialize a Publisher client.
# credentials must be loaded from a file, so we temporarily create ibe
with open('gcloud-key.json', 'w') as outfile:
outfile.write(settings.GOOGLE_APPLICATION_CREDENTIALS)
outfile.close()
credentials = service_account.Credentials. from_service_account_file('gcloud-key.json')
client = pubsub_v1.PublisherClient(credentials=credentials)
os.remove('gcloud-key.json') # important!!!

# Create a fully qualified identifier in the form of
# `projects/{project_id}/topics/{topic_name}`
topic_path = client.topic_path(project_id, topic_name)

# Data sent to Cloud Pub/Sub must be a bytestring.
#data = b"examplefuncs"
if data == "":
data = b"sample pub/sub message"

# Keep track of the number of published messages.
ref = dict({"num_messages": 0})

# When you publish a message, the client returns a future.
api_future = client.publish(topic_path, data=data)
api_future.add_done_callback(get_callback(api_future, data, ref))

# Keep the main thread from exiting while the message future
# gets resolved in the background.
while api_future.running():
time.sleep(0.5)
# print("Published {} message(s).".format(ref["num_messages"]))
# Repeat while this fails, because the data is already in the
# database. The pub/sub message needs to be enqueued to ensure the
# request is complete.
for i in range(num_retries):
try:
# Initialize a Publisher client.
# credentials must be loaded from a file, so we temporarily create ibe
with open('gcloud-key.json', 'w') as outfile:
outfile.write(settings.GOOGLE_APPLICATION_CREDENTIALS)
outfile.close()
credentials = service_account.Credentials. from_service_account_file('gcloud-key.json')
client = pubsub_v1.PublisherClient(credentials=credentials)
os.remove('gcloud-key.json') # important!!!

# Create a fully qualified identifier in the form of
# `projects/{project_id}/topics/{topic_name}`
topic_path = client.topic_path(project_id, topic_name)

# Data sent to Cloud Pub/Sub must be a bytestring.
#data = b"examplefuncs"
if data == "":
data = b"sample pub/sub message"

# Keep track of the number of published messages.
ref = dict({"num_messages": 0})

# When you publish a message, the client returns a future.
api_future = client.publish(topic_path, data=data)
api_future.add_done_callback(get_callback(api_future, data, ref))

# Keep the main thread from exiting while the message future
# gets resolved in the background.
while api_future.running():
time.sleep(0.5)
# print("Published {} message(s).".format(ref["num_messages"]))
except:
pass
else:
break

def scrimmage_pub_sub_call(red_submission_id, blue_submission_id, red_team_name, blue_team_name, scrimmage_id, scrimmage_replay, map_ids=None):

Expand Down
2 changes: 2 additions & 0 deletions backend/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,14 @@
"WaterBot",
"CentralSoup",
"ChristmasInJuly",
"CosmicBackgroundRadiation",
"ClearlyTwelveHorsesInASalad",
"CowFarm",
"DidAMonkeyMakeThis",
"GSF",
"Hills",
"InADitch",
"Infinity",
"Islands",
"IsThisProcedural",
"OmgThisIsProcedural",
Expand Down
2 changes: 1 addition & 1 deletion client/visualizer/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export enum Mode {
export function defaults(supplied?: any): Config {
supplied = supplied || {};
return {
gameVersion: supplied.gameVersion || "2020.1.1.2", //TODO: Change this on each release!
gameVersion: supplied.gameVersion || "2020.2.0.0", //TODO: Change this on each release!
fullscreen: supplied.fullscreen || false,
width: supplied.width || 600,
height: supplied.height || 600,
Expand Down
2 changes: 2 additions & 0 deletions client/visualizer/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,14 @@ export const SERVER_MAPS: Map<string, MapType> = new Map<string, MapType>([
["WaterBot", MapType.DEFAULT],
["CentralSoup", MapType.DEFAULT],
["ChristmasInJuly", MapType.SPRINT],
["CosmicBackgroundRadiation", MapType.SPRINT],
["ClearlyTwelveHorsesInASalad", MapType.SPRINT],
["CowFarm", MapType.SPRINT],
["DidAMonkeyMakeThis", MapType.SPRINT],
["GSF", MapType.SPRINT],
["Hills", MapType.SPRINT],
["InADitch", MapType.SPRINT],
["Infinity", MapType.SPRINT],
["Islands", MapType.SPRINT],
["IsThisProcedural", MapType.SPRINT],
["OmgThisIsProcedural", MapType.SPRINT],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ public enum GameActionExceptionType {
*/
NO_ROBOT_THERE,
/**
* Indicates when a robot tries to send too many messages to the blockchain.
* Indicates when a robot tries to messages of an incorrect size to the blockchain.
*/
TOO_LONG_BLOCKCHAIN_TRANSACTION,
INCORRECT_BLOCKCHAIN_TRANSACTION_LENGTH,
/**
* Indicates when round number is out of range.
*/
Expand Down
2 changes: 1 addition & 1 deletion engine/src/main/battlecode/common/GameConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public static float getWaterLevel(int roundNumber) {
// *********************************

/** The maximum number of integers that can be sent in one message. */
public static final int MAX_BLOCKCHAIN_TRANSACTION_LENGTH = 7;
public static final int BLOCKCHAIN_TRANSACTION_LENGTH = 7;

/** The number of transactions that get broadcasted every round. */
public static final int NUMBER_OF_TRANSACTIONS_PER_BLOCK = 7;
Expand Down
79 changes: 57 additions & 22 deletions engine/src/main/battlecode/common/RobotController.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,6 @@ public strictfp interface RobotController {
*/
int getTeamSoup();

/**
* Returns the number of robots on your team (including your HQ).
* If this number ever reaches zero, the opposing team will automatically
* win by destruction (because your HQ is dead).
*
* @return the number of robots on your team
*
* @battlecode.doc.costlymethod
*/
int getRobotCount();

/**
* Returns the width of the map.
*
Expand Down Expand Up @@ -150,16 +139,15 @@ public strictfp interface RobotController {
// ***********************************

/**
* Senses whether a MapLocation is on the map. Will throw an exception if
* the location is not within the sensor range.
* Senses whether a MapLocation is on the map.
* This is different from before sprint rebalancing.
*
* @param loc the location to check
* @return true if the location is on the map; false otherwise.
* @throws GameActionException if the location is not within sensor range.
*
* @battlecode.doc.costlymethod
*/
boolean onTheMap(MapLocation loc) throws GameActionException;
boolean onTheMap(MapLocation loc);

/**
* Senses whether the given location is within the robot's sensor range, and if it is on the map.
Expand Down Expand Up @@ -270,15 +258,53 @@ public strictfp interface RobotController {
* increasing distance from the specified center.
*
* @param center center of the given search radius
* @param radius return robots this distance away from the given center
* @param radiusSquared return robots this distance squared away from the given center
* location. If -1 is passed, all robots within sense radius are returned
* @param team filter game objects by the given team. If null is passed,
* objects from all teams are returned
* @return sorted array of RobotInfo objects of the robots you sensed.
*
* @battlecode.doc.costlymethod
*/
RobotInfo[] senseNearbyRobots(MapLocation center, int radius, Team team);
RobotInfo[] senseNearbyRobots(MapLocation center, int radiusSquared, Team team);

/**
* Returns all map locations containing soup within sense radius. The
* locations are returned in no particular order.
*
* @return array of map locations that can be sensed containing soup
*
* @battlecode.doc.costlymethod
*/
MapLocation[] senseNearbySoup();

/**
* Returns all map locations that can be sensed containing soup within
* specified radius. The locations are returned in no particular order.
*
* @param radiusSquared return soup locations this distance away from the center of
* this robot. If -1 is passed, all locations with soup within sense radius are returned
* @return array of map locations that can be sensed within the
* specified radius containing soup
*
* @battlecode.doc.costlymethod
*/
MapLocation[] senseNearbySoup(int radiusSquared);

/**
* Returns all map locations that can be sensed containing soup within
* specified radius of specified location. The locations are returned in no
* particular order.
*
* @param center center of the given search radius
* @param radiusSquared return soup locations this distance away from the center of
* this robot. If -1 is passed, all locations with soup within sense radius are returned
* @return array of map locations that can be sensed within the
* specified radius containing soup
*
* @battlecode.doc.costlymethod
*/
MapLocation[] senseNearbySoup(MapLocation center, int radiusSquared);

/**
* Returns the crude soup count at a given location, if the location is
Expand Down Expand Up @@ -637,6 +663,13 @@ public strictfp interface RobotController {
// ****** OTHER ACTION METHODS *******
// ***********************************

/**
* Causes the robot to die.
*
* @battlecode.doc.costlymethod
*/
void disintegrate() throws GameActionException;

/**
* Causes your team to lose the game. It's like typing "gg."
*
Expand All @@ -649,11 +682,11 @@ public strictfp interface RobotController {
// ***********************************

/**
* Tests if the robot can submit a transaction
* Checks that the robot can submit a transaction
* to the blockchain at the indicated cost. Tests if the team has enough soup,
* that the provided cost is positive, and that the message doesn't exceed the limit.
* that the provided cost is positive, and that the message contains exactly 7 integers.
*
* @param message the list of ints to send (at most of GameConstants.MAX_BLOCKCHAIN_TRANSACTION_LENGTH many).
* @param message the list of ints to send (exactly GameConstants.BLOCKCHAIN_TRANSACTION_LENGTH of them).
* @param cost the price that the unit is willing to pay for the message, in soup
*
* @return whether the transaction can be submitted or not
Expand All @@ -664,12 +697,13 @@ public strictfp interface RobotController {

/**
* Submits a transaction to the transaction pool at the indicated cost.
* The transaction messages needs to be exactly 7 integers.
*
* @param message the list of ints to send.
* @param cost the price that the unit is willing to pay for the message
*
* @throws GameActionException if the team does not have enough soup to cover the cost,
* if the message exceeds the allowed limit, or if the cost is negative
* if the message is not of the right size, or if the cost is negative
*
* @battlecode.doc.costlymethod
*/
Expand All @@ -678,7 +712,8 @@ public strictfp interface RobotController {

/**
* Get the block of messages that was approved at a given round.
* The block will contain a list of transactions.
* The block will contain a list of transactions, and each transaction
* message will have exactly 7 integers.
*
* @param roundNumber the round index.
* @return an array of Transactions that were accepted into the blockchain
Expand Down
Loading

0 comments on commit 457f9c2

Please sign in to comment.