data-analytics/minigolf-demo/bq_notebook.ipynb (246 lines of code) (raw):
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "82d78978",
"metadata": {},
"outputs": [],
"source": [
"# Copyright 2024 Google LLC\n",
"\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"id": "V3Ij8Ar6W3sr",
"metadata": {
"id": "V3Ij8Ar6W3sr"
},
"source": [
"### Import necessary Libraries"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5dd06c83",
"metadata": {},
"outputs": [],
"source": [
"from google.cloud import bigquery, storage\n",
"import matplotlib.pyplot as plt\n",
"from IPython.display import display, Markdown, Image"
]
},
{
"cell_type": "markdown",
"id": "-1_xw_2cRBYH",
"metadata": {
"id": "-1_xw_2cRBYH"
},
"source": [
"### Define Constants"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c9069a53",
"metadata": {},
"outputs": [],
"source": [
"USER_NUM = \"0000\" # @param {type:\"string\"}\n",
"USER_ID = f\"minigolf_{USER_NUM}\"\n",
"PROJECT_ID = \"\"\n",
"BACKGROUND_IMAGE_BUCKET = \"\"\n",
"BQ_DATASET = \"\"\n",
"BQ_PREFIX = f\"{PROJECT_ID}.{BQ_DATASET}\""
]
},
{
"cell_type": "markdown",
"id": "iIgaoZL185OG",
"metadata": {
"id": "iIgaoZL185OG"
},
"source": [
"### Golf with Gemini - Statistical Analysis\n",
"This section provides a statistical overview of your performance on the course by analyzing game data from all players.\n",
"\n",
"We utilize the following key statistical indicators:\n",
"\n",
"* **Average Score**: This shows the average score for all players, giving you an idea of how challenging the course is overall.\n",
"* **Median Score**: This score is the middle value when all scores are listed from lowest to highest. It's helpful because it's less affected by extreme scores, giving a more balanced view.\n",
"To make things even clearer, we've included a bar graph that visually shows the distribution of scores. This helps you see how many players fall into different score ranges.\n",
"\n",
"Use this information to compare your performance to others and get a better understanding of your own golf game!"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ujTQgrJRmfle",
"metadata": {
"id": "ujTQgrJRmfle"
},
"outputs": [],
"source": [
"# Configure BigQuery client\n",
"bq_client = bigquery.Client()\n",
"query = f\"SELECT * FROM {BQ_PREFIX}.tracking\"\n",
"\n",
"df = bq_client.query(query).to_dataframe()\n",
"last_frame_per_user = df.groupby('user_id')['frame_number'].transform(max)\n",
"df_filtered = df[df['frame_number'] == last_frame_per_user]\n",
"df_filtered = df_filtered[df_filtered['distance'] < 30]\n",
"user_shot_counts = df_filtered.groupby('user_id')['shot_number'].first()\n",
"user_shot_counts = user_shot_counts[user_shot_counts > 0]\n",
"shot_number_freq = user_shot_counts.value_counts()\n",
"\n",
"# Selected user's number of shots\n",
"num_users = df['user_id'].nunique()\n",
"user_shots = user_shot_counts.get(USER_ID, 0)\n",
"average_shots_per_user = user_shot_counts.mean()\n",
"median_shots_per_user = user_shot_counts.median()\n",
"\n",
"display(Markdown(f\"### There are {num_users} users played so far.\"))\n",
"display(Markdown(f\"### User {USER_ID}'s number of shots: {user_shots}\"))\n",
"display(Markdown(f\"### Average number of shots: {average_shots_per_user:.2f}\"))\n",
"display(Markdown(f\"### Median number of shots: {median_shots_per_user:.2f}\"))\n",
"\n",
"# Transform the 'shot_number_freq' Series into a DataFrame\n",
"table_data = shot_number_freq.to_frame().reset_index() \n",
"table_data.columns = ['Number of Shots', 'Number of Users']\n",
"display(table_data)\n",
"\n",
"# Plot a bar chart\n",
"plt.xlim(0, 9)\n",
"barlist = plt.bar(shot_number_freq.index, shot_number_freq.values, color='#4285F4')\n",
"plt.xlabel('Number of Shots')\n",
"plt.ylabel('Number of Users')\n",
"plt.title('Distribution of Number of Shots per User')\n",
"\n",
"# Highlight the bar corresponding to user_shots\n",
"if user_shots in shot_number_freq.index:\n",
" barlist[shot_number_freq.index.get_loc(user_shots)].set_color('#34A853')\n",
" plt.legend([barlist[shot_number_freq.index.get_loc(user_shots)]], [f'Shot Number of {USER_ID}'])\n",
"\n",
"plt.xticks(range(9))\n",
"\n",
"plt.show()\n"
]
},
{
"cell_type": "markdown",
"id": "J33U5kj03Ky4",
"metadata": {
"id": "J33U5kj03Ky4"
},
"source": [
"### Visualizing Your Play\n",
"\n",
"This graph provides a bird's-eye view of your mini-golf journey, showing exactly how your ball traveled across the course. The dots represent the ball's position in each frame, and their color indicates the order of your shots.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "tn_z4A681DAz",
"metadata": {
"id": "tn_z4A681DAz"
},
"outputs": [],
"source": [
"# Create a storage client\n",
"storage_client = storage.Client()\n",
"\n",
"# Download the file\n",
"bucket = storage_client.bucket(BACKGROUND_IMAGE_BUCKET)\n",
"file_name = f\"{USER_ID}.png\"\n",
"blob = bucket.blob(file_name)\n",
"blob.download_to_filename(file_name)\n",
"\n",
"# Display the image\n",
"Image(filename=file_name)\n"
]
},
{
"cell_type": "markdown",
"id": "CAM0FCRf3Sqx",
"metadata": {
"id": "CAM0FCRf3Sqx"
},
"source": [
"### Gemini: The AI Sportscaster\n",
"\n",
"Imagine Gemini as a super-smart assistant who watches your mini-golf game. It can't see you swing the club, but it follows the ball using a video camera, acting like a data detective. Gemini analyzes the video frame-by-frame, tracking the ball's path and how close it gets to the hole.\n",
"\n",
"Once Gemini understands the game, it transforms into a real announcer, describing each shot with excitement and flair. But instead of a human voice, it uses its artificial intelligence to generate the commentary. This is possible because Gemini has been trained on a massive amount of sportscasting data, learning the language, style, and energy that announcers bring to the game.\n",
"\n",
"The best part? Gemini does all this in real-time! As soon as you finish a hole, it instantly generates commentary, providing insights without any manual effort. It's like having a combination of a data analyst and a sports announcer, all powered by AI. Gemini takes the \"what\" (video data) and turns it into the \"how\" (play-by-play) using its knowledge of sportscasting gleaned from vast amounts of training data.\n",
"\n",
"So, whether you're a guest enjoying the game or a presenter explaining the technology, think of Gemini as your AI sportscaster, bringing a unique and insightful perspective to the mini-golf experience!\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5RvCZieY1S4h",
"metadata": {
"id": "5RvCZieY1S4h"
},
"outputs": [],
"source": [
"query = f\"SELECT * FROM {BQ_PREFIX}.commentary WHERE user_id = '{USER_ID}'\"\n",
"\n",
"df = bq_client.query(query).to_dataframe()\n",
"display(Markdown(df[\"commentary\"][0]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5d65f02f",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"colab": {
"name": "Comprehensive",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}