<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dhani Dzulkarnain</title>
    <description>The latest articles on DEV Community by Dhani Dzulkarnain (@dhani_dzulkarnain).</description>
    <link>https://dev.to/dhani_dzulkarnain</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2453741%2Ff7b1a790-3eca-467d-af29-c9f55571723e.png</url>
      <title>DEV Community: Dhani Dzulkarnain</title>
      <link>https://dev.to/dhani_dzulkarnain</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dhani_dzulkarnain"/>
    <language>en</language>
    <item>
      <title>Building OpponentIQ: Automating Esports Scouting with GRID API</title>
      <dc:creator>Dhani Dzulkarnain</dc:creator>
      <pubDate>Fri, 23 Jan 2026 08:08:55 +0000</pubDate>
      <link>https://dev.to/dhani_dzulkarnain/building-opponentiq-automating-esports-scouting-with-grid-api-kp3</link>
      <guid>https://dev.to/dhani_dzulkarnain/building-opponentiq-automating-esports-scouting-with-grid-api-kp3</guid>
      <description>&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In competitive esports, preparation is everything. Professional teams spend hours analyzing opponents through VOD reviews, manually tracking statistics, and compiling notes from scattered data sources. What if we could automate this entire process using real competitive data?&lt;/p&gt;

&lt;p&gt;That's exactly what I set out to build for the Sky's the Limit - Cloud9 x JetBrains Hackathon.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is OpponentIQ?
&lt;/h2&gt;

&lt;p&gt;OpponentIQ is an AI-powered scouting report generator that automatically analyzes any League of Legends or VALORANT team using official match data from GRID API. In seconds, coaches and players get a comprehensive breakdown including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Team strategies&lt;/strong&gt;: Win rates, composition patterns, and macro tendencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Player analysis&lt;/strong&gt;: Individual stats, champion/agent pools, and KDA metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actionable insights&lt;/strong&gt;: Data-driven recommendations like "Neutralize [Player] - target bans recommended"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export capabilities&lt;/strong&gt;: Professional PDF reports and JSON data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Backend: Python + FastAPI
&lt;/h3&gt;

&lt;p&gt;I chose FastAPI for its speed and automatic API documentation. The backend handles three main responsibilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GRID API Integration&lt;/strong&gt; - Fetching real match data via GraphQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Processing&lt;/strong&gt; - Analyzing patterns and calculating statistics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Report Generation&lt;/strong&gt; - Transforming raw data into actionable insights&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The GRID API Challenge
&lt;/h3&gt;

&lt;p&gt;GRID's esports data is incredibly comprehensive but split across two endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Central Data API&lt;/strong&gt;: Team metadata and series IDs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Series State API&lt;/strong&gt;: Detailed game statistics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I implemented a two-stage retrieval system that fetches series information first, then queries detailed stats for each match. This required careful GraphQL query optimization to keep response times under 5 seconds even when analyzing 10+ matches.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Simplified example of the two-stage approach
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_team_matches&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_matches&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Stage 1: Get series IDs from Central Data
&lt;/span&gt;    &lt;span class="n"&gt;series_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;central_data_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;team_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_matches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Stage 2: Get detailed stats from Series State
&lt;/span&gt;    &lt;span class="n"&gt;matches_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;series_id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;series_ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;match_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;series_state_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;series_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;matches_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;matches_data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Data Analysis Engine
&lt;/h2&gt;

&lt;p&gt;The scouting_analyzer.py module processes match data to generate insights:&lt;/p&gt;

&lt;p&gt;For League of Legends:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infers player roles (not provided by API)&lt;/li&gt;
&lt;li&gt;Identifies champion pools and ban priorities&lt;/li&gt;
&lt;li&gt;Calculates KDA ratios and performance trends&lt;/li&gt;
&lt;li&gt;Detects team composition patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For VALORANT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracks agent selections and map preferences&lt;/li&gt;
&lt;li&gt;Calculates Average Combat Score (ACS)&lt;/li&gt;
&lt;li&gt;Analyzes headshot percentages&lt;/li&gt;
&lt;li&gt;Identifies team composition meta&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Frontend: Clean and Responsive
&lt;/h2&gt;

&lt;p&gt;I built the UI with HTML5, Bootstrap 5, and vanilla JavaScript. Key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Galaxy-themed animation: A stunning opening curtain reveal&lt;/li&gt;
&lt;li&gt;Interactive charts: Chart.js visualizations for performance trends&lt;/li&gt;
&lt;li&gt;Real-time loading: Progress indicators with status updates&lt;/li&gt;
&lt;li&gt;Export functionality: PDF generation using jsPDF&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Development Experience with PyCharm
&lt;/h2&gt;

&lt;p&gt;Using JetBrains PyCharm throughout this project was a game-changer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intelligent code completion saved hours during FastAPI development&lt;/li&gt;
&lt;li&gt;Integrated debugging helped solve the role inference logic quickly&lt;/li&gt;
&lt;li&gt;GraphQL query formatting made API integration cleaner&lt;/li&gt;
&lt;li&gt;Git integration streamlined version control&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Data Transparency
&lt;/h3&gt;

&lt;p&gt;When GRID API doesn't provide certain data (like specific VALORANT map names in some responses), I had a choice: fabricate placeholder data or be transparent.&lt;/p&gt;

&lt;p&gt;I chose transparency. OpponentIQ displays "Unknown" when data isn't available, maintaining credibility over aesthetics.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Role Inference for League of Legends
&lt;/h3&gt;

&lt;p&gt;Player roles aren't explicitly provided by GRID's LoL API. I implemented logic to infer roles based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Champion selections (e.g., Jarvan IV → likely Jungle)&lt;/li&gt;
&lt;li&gt;Game positions and farm patterns&lt;/li&gt;
&lt;li&gt;Historical role patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Generating Actionable Insights
&lt;/h3&gt;

&lt;p&gt;Raw statistics are useful, but coaches need actionable strategies. I built algorithms that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify star players (high KDA) and recommend target bans&lt;/li&gt;
&lt;li&gt;Detect weak performers and suggest lane exploitation&lt;/li&gt;
&lt;li&gt;Analyze team form and recommend aggression levels&lt;/li&gt;
&lt;li&gt;Parse ban priorities to suggest counter-picks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example insight generated:&lt;br&gt;
"Neutralize Keria"Keria (Support) has 4.64 KDA - target bans on Milio recommended&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;OpponentIQ successfully generates professional scouting reports with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ 100% live GRID API integration (zero mock data)&lt;/li&gt;
&lt;li&gt;✅ Multi-game support (League of Legends + VALORANT)&lt;/li&gt;
&lt;li&gt;✅ PDF export for team meetings&lt;/li&gt;
&lt;li&gt;✅ Historical tracking for opponent evolution&lt;/li&gt;
&lt;li&gt;✅ Sub-5-second response times for 10-match analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;GraphQL optimization is critical for performance with nested queries&lt;/li&gt;
&lt;li&gt;Data transparency builds more trust than fake placeholders&lt;/li&gt;
&lt;li&gt;User experience matters - loading animations and progress bars make waiting feel shorter&lt;/li&gt;
&lt;li&gt;Production-ready means handling edge cases gracefully&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;The project is fully open source:&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/DhaniDzulkarnain1/Cloud9-Hackathon" rel="noopener noreferrer"&gt;https://github.com/DhaniDzulkarnain1/Cloud9-Hackathon&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Demo Video: &lt;a href="https://youtu.be/QvMQ0h0xhCM" rel="noopener noreferrer"&gt;https://youtu.be/QvMQ0h0xhCM&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Start:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the repository&lt;/span&gt;
git clone https://github.com/DhaniDzulkarnain1/Cloud9-Hackathon.git

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Run the backend&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;backend
python3 main.py

&lt;span class="c"&gt;# Open frontend/index.html in your browser&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;I'm planning to expand OpponentIQ with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More games: CS:GO, Dota 2, Rocket League&lt;/li&gt;
&lt;li&gt;Win prediction: Machine learning models for match outcomes&lt;/li&gt;
&lt;li&gt;Team comparison: Side-by-side opponent analysis&lt;/li&gt;
&lt;li&gt;Live integration: Real-time scouting during tournaments&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building OpponentIQ taught me that the best tools solve real problems. Esports teams need efficient opponent analysis, and by leveraging GRID's official data API, I created something that could genuinely help coaches and players prepare for matches.&lt;/p&gt;

&lt;p&gt;If you're interested in esports analytics, data visualization, or just want to see how to integrate the GRID API into your projects, check out the code on GitHub!&lt;/p&gt;




&lt;p&gt;Built for: Sky's the Limit - Cloud9 x JetBrains Hackathon 2025&lt;br&gt;
Category: Category 2 - GRID API Integration&lt;br&gt;
Tech Stack: Python, FastAPI, GRID API, Bootstrap 5, Chart.js, JetBrains PyCharm&lt;/p&gt;

</description>
      <category>python</category>
      <category>fastapi</category>
      <category>esports</category>
      <category>hackathon</category>
    </item>
    <item>
      <title>Connecting database with API</title>
      <dc:creator>Dhani Dzulkarnain</dc:creator>
      <pubDate>Tue, 19 Nov 2024 09:46:28 +0000</pubDate>
      <link>https://dev.to/dhani_dzulkarnain/connecting-database-with-api-29bm</link>
      <guid>https://dev.to/dhani_dzulkarnain/connecting-database-with-api-29bm</guid>
      <description>&lt;p&gt;can anyone help me, so I made a mobile platform and the two websites are integrated with each other, then this website functions as a collector and mobile as a fisherman, the relationship between these two platforms is to record fish catches, and for this mobile I have created a frontend display using Jetpack Compose, then for the backend, how can I connect via API, for the database created using MySQL.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
