Initial commit
This commit is contained in:
commit
5010af7384
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
@ -0,0 +1,3 @@
|
||||
## 1.0.0
|
||||
|
||||
- Initial version.
|
30
analysis_options.yaml
Normal file
30
analysis_options.yaml
Normal file
@ -0,0 +1,30 @@
|
||||
# This file configures the static analysis results for your project (errors,
|
||||
# warnings, and lints).
|
||||
#
|
||||
# This enables the 'recommended' set of lints from `package:lints`.
|
||||
# This set helps identify many issues that may lead to problems when running
|
||||
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
|
||||
# style and format.
|
||||
#
|
||||
# If you want a smaller set of lints you can change this to specify
|
||||
# 'package:lints/core.yaml'. These are just the most critical lints
|
||||
# (the recommended set includes the core lints).
|
||||
# The core lints are also what is used by pub.dev for scoring packages.
|
||||
|
||||
include: package:lints/recommended.yaml
|
||||
|
||||
# Uncomment the following section to specify additional rules.
|
||||
|
||||
# linter:
|
||||
# rules:
|
||||
# - camel_case_types
|
||||
|
||||
# analyzer:
|
||||
# exclude:
|
||||
# - path/to/excluded/files/**
|
||||
|
||||
# For more information about the core and recommended set of lints, see
|
||||
# https://dart.dev/go/core-lints
|
||||
|
||||
# For additional information about configuring this file, see
|
||||
# https://dart.dev/guides/language/analysis-options
|
25
bin/main.dart
Normal file
25
bin/main.dart
Normal file
@ -0,0 +1,25 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:overfast_api/client.dart';
|
||||
import 'package:overfast_api/utils/types.dart';
|
||||
|
||||
void main(List<String> args) async {
|
||||
final client = Overfast();
|
||||
|
||||
// final me = client.players.player('Rapougnac-2980');
|
||||
|
||||
// final stats = await me.statsSummary();
|
||||
|
||||
// print(stats.heroes['doomfist']!.gamesWon);
|
||||
|
||||
// final doom = await client.heroes.hero(Hero.doomfist,locale: Locale.frFr);
|
||||
|
||||
// print(doom.description);
|
||||
|
||||
// final heroes = await client.heroes.heroes(locale: Locale.frFr);
|
||||
|
||||
// print(jsonEncode(heroes));
|
||||
|
||||
final hero = client.heroes.hero(HeroKey.junkerqueen, locale: Locale.frFr);
|
||||
print(hero);
|
||||
}
|
40
lib/client.dart
Normal file
40
lib/client.dart
Normal file
@ -0,0 +1,40 @@
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:overfast_api/heroes/heroes.dart';
|
||||
import 'package:overfast_api/players/players.dart';
|
||||
|
||||
import './utils/utils.dart' as utils;
|
||||
import 'maps/maps.dart';
|
||||
|
||||
class Overfast {
|
||||
final Uri baseUri;
|
||||
|
||||
late final Future<T> Function<T>(
|
||||
String, [
|
||||
Map<String, dynamic>,
|
||||
]) get;
|
||||
|
||||
late final Future<List<T>> Function<T>(
|
||||
String, [
|
||||
Map<String, dynamic>,
|
||||
]) getList;
|
||||
|
||||
final client = http.Client();
|
||||
|
||||
|
||||
late final Maps maps;
|
||||
late final Players players;
|
||||
late final Heroes heroes;
|
||||
|
||||
Overfast([Uri? baseUri])
|
||||
: baseUri = baseUri ?? Uri.https('overfast-api.tekrop.fr') {
|
||||
get = utils.get(client, this.baseUri);
|
||||
getList = utils.getList(client, this.baseUri);
|
||||
maps = Maps(this);
|
||||
players = Players(this);
|
||||
heroes = Heroes(this);
|
||||
}
|
||||
|
||||
void close() {
|
||||
client.close();
|
||||
}
|
||||
}
|
34
lib/heroes/heroes.dart
Normal file
34
lib/heroes/heroes.dart
Normal file
@ -0,0 +1,34 @@
|
||||
import 'package:overfast_api/client.dart';
|
||||
import 'package:overfast_api/heroes/heroes_data.dart' as data;
|
||||
import 'package:overfast_api/utils/types.dart';
|
||||
|
||||
class Heroes {
|
||||
final Overfast _client;
|
||||
|
||||
const Heroes(this._client);
|
||||
|
||||
Future<List<data.Hero>> heroes({Role? role, Locale? locale}) =>
|
||||
_client.getList<data.Hero>(
|
||||
'/heroes',
|
||||
{
|
||||
if (role != null) 'role': role.toString(),
|
||||
if (locale != null) 'locale': locale.toString(),
|
||||
},
|
||||
);
|
||||
|
||||
Future<data.HeroDetails> hero(HeroKey hero, {Locale? locale}) =>
|
||||
_client.get<data.HeroDetails>(
|
||||
'/heroes/${hero.heroName}',
|
||||
{
|
||||
if (locale != null) 'locale': locale.toString(),
|
||||
},
|
||||
);
|
||||
|
||||
Future<List<data.Roles>> roles({Locale? locale}) =>
|
||||
_client.getList<data.Roles>(
|
||||
'/roles',
|
||||
{
|
||||
if (locale != null) 'locale': locale.toString(),
|
||||
},
|
||||
);
|
||||
}
|
284
lib/heroes/heroes_data.dart
Normal file
284
lib/heroes/heroes_data.dart
Normal file
@ -0,0 +1,284 @@
|
||||
import 'package:overfast_api/utils/types.dart';
|
||||
|
||||
class Hero {
|
||||
final String name;
|
||||
final HeroKey key;
|
||||
final String? portrait;
|
||||
final Role role;
|
||||
|
||||
const Hero({
|
||||
required this.name,
|
||||
required this.key,
|
||||
this.portrait,
|
||||
required this.role,
|
||||
});
|
||||
|
||||
factory Hero.fromJson(Map<String, dynamic> json) {
|
||||
return Hero(
|
||||
name: json['name'],
|
||||
key: HeroKey.fromString(json['key']),
|
||||
portrait: json['portrait'],
|
||||
role: Role.fromString(json['role']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'key': key.name,
|
||||
'portrait': portrait,
|
||||
'role': role.toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class HeroDetails extends Hero {
|
||||
final String location;
|
||||
final List<Ability> abilities;
|
||||
final Map? hitpoints;
|
||||
final Story story;
|
||||
final String description;
|
||||
final int age;
|
||||
final String? birthday;
|
||||
|
||||
|
||||
const HeroDetails({
|
||||
required super.name,
|
||||
required super.role,
|
||||
super.portrait,
|
||||
required this.description,
|
||||
required this.story,
|
||||
required this.location,
|
||||
required this.abilities,
|
||||
this.hitpoints,
|
||||
// Stub
|
||||
super.key = HeroKey.eemptyy,
|
||||
required this.age,
|
||||
required this.birthday,
|
||||
});
|
||||
|
||||
factory HeroDetails.fromJson(Map<String, dynamic> json) {
|
||||
return HeroDetails(
|
||||
name: json['name'],
|
||||
description: (json['description']),
|
||||
portrait: json['portrait'],
|
||||
role: Role.fromString(json['role']),
|
||||
location: json['location'],
|
||||
abilities:
|
||||
(json['abilities'] as List).map((e) => Ability.fromJson(e)).toList(),
|
||||
hitpoints: json['hitpoints'],
|
||||
story: Story.fromJson(json['story']),
|
||||
age: json['age'],
|
||||
birthday: json['birthday'],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'portrait': portrait,
|
||||
'role': role.toString(),
|
||||
'location': location,
|
||||
'abilities': abilities.map((e) => e.toJson()).toList(),
|
||||
'hitpoints': hitpoints,
|
||||
'story': story.toJson(),
|
||||
'age': age,
|
||||
'birthday': birthday,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Ability {
|
||||
final String name;
|
||||
final String description;
|
||||
final String icon;
|
||||
final Video video;
|
||||
|
||||
const Ability({
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.icon,
|
||||
required this.video,
|
||||
});
|
||||
|
||||
factory Ability.fromJson(Map<String, dynamic> json) {
|
||||
return Ability(
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
icon: json['icon'],
|
||||
video: Video.fromJson(json['video']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'description': description,
|
||||
'icon': icon,
|
||||
'video': video.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Video {
|
||||
final String thumbnail;
|
||||
final Link link;
|
||||
|
||||
const Video({
|
||||
required this.thumbnail,
|
||||
required this.link,
|
||||
});
|
||||
|
||||
factory Video.fromJson(Map<String, dynamic> json) {
|
||||
return Video(
|
||||
thumbnail: json['thumbnail'],
|
||||
link: Link.fromJson(json['link']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'thumbnail': thumbnail,
|
||||
'link': link.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Link {
|
||||
final String mp4;
|
||||
final String webm;
|
||||
|
||||
const Link({
|
||||
required this.mp4,
|
||||
required this.webm,
|
||||
});
|
||||
|
||||
factory Link.fromJson(Map<String, dynamic> json) {
|
||||
return Link(
|
||||
mp4: json['mp4'],
|
||||
webm: json['webm'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'mp4': mp4,
|
||||
'webm': webm,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Story {
|
||||
final String summary;
|
||||
final Media? media;
|
||||
final List<Chapter> chapters;
|
||||
|
||||
const Story({
|
||||
required this.summary,
|
||||
required this.media,
|
||||
required this.chapters,
|
||||
});
|
||||
|
||||
factory Story.fromJson(Map<String, dynamic> json) {
|
||||
return Story(
|
||||
summary: json['summary'],
|
||||
media: json['media'] != null ? Media.fromJson(json['media']) : null,
|
||||
chapters:
|
||||
(json['chapters'] as List).map((e) => Chapter.fromJson(e)).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'summary': summary,
|
||||
if (media != null) 'media': media!.toJson(),
|
||||
'chapters': chapters.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Media {
|
||||
final String type;
|
||||
final String link;
|
||||
|
||||
const Media({
|
||||
required this.type,
|
||||
required this.link,
|
||||
});
|
||||
|
||||
factory Media.fromJson(Map<String, dynamic> json) {
|
||||
return Media(
|
||||
type: json['type'],
|
||||
link: json['link'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'type': type,
|
||||
'link': link,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Chapter {
|
||||
final String title;
|
||||
final String content;
|
||||
final String picture;
|
||||
|
||||
const Chapter({
|
||||
required this.title,
|
||||
required this.content,
|
||||
required this.picture,
|
||||
});
|
||||
|
||||
factory Chapter.fromJson(Map<String, dynamic> json) {
|
||||
return Chapter(
|
||||
title: json['title'],
|
||||
content: json['content'],
|
||||
picture: json['picture'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'title': title,
|
||||
'content': content,
|
||||
'picture': picture,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Roles {
|
||||
final Role key;
|
||||
final String name;
|
||||
final String icon;
|
||||
final String description;
|
||||
|
||||
const Roles({
|
||||
required this.key,
|
||||
required this.name,
|
||||
required this.icon,
|
||||
required this.description,
|
||||
});
|
||||
|
||||
factory Roles.fromJson(Map<String, dynamic> json) {
|
||||
return Roles(
|
||||
key: Role.fromString(json['key']),
|
||||
name: json['name'],
|
||||
icon: json['icon'],
|
||||
description: json['description'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'key': key.toString(),
|
||||
'name': name,
|
||||
'icon': icon,
|
||||
'description': description,
|
||||
};
|
||||
}
|
||||
}
|
92
lib/maps/maps.dart
Normal file
92
lib/maps/maps.dart
Normal file
@ -0,0 +1,92 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:overfast_api/client.dart';
|
||||
import 'package:overfast_api/utils/utils.dart';
|
||||
|
||||
enum Gamemode {
|
||||
assault,
|
||||
captureTheFlag,
|
||||
control,
|
||||
deathmatch,
|
||||
elimination,
|
||||
escort,
|
||||
hybrid,
|
||||
push,
|
||||
teamDeathmatch,
|
||||
flashpoint,
|
||||
clash;
|
||||
|
||||
@override
|
||||
String toString() => toKebabCase(name);
|
||||
|
||||
static Gamemode fromString(String value) {
|
||||
return Gamemode.values.firstWhere((e) => e.toString() == value);
|
||||
}
|
||||
}
|
||||
|
||||
final class GameMap {
|
||||
final String name;
|
||||
final List<Gamemode> gamemodes;
|
||||
final String screenshot;
|
||||
final String location;
|
||||
final String? countryCode;
|
||||
|
||||
const GameMap({
|
||||
required this.name,
|
||||
required this.gamemodes,
|
||||
required this.screenshot,
|
||||
required this.location,
|
||||
this.countryCode,
|
||||
});
|
||||
|
||||
// Stub empty constructor
|
||||
GameMap.empty() : this(name: '', gamemodes: [], screenshot: '', location: '');
|
||||
|
||||
factory GameMap.fromJson(Map<String, dynamic> json) {
|
||||
return GameMap(
|
||||
name: json['name'],
|
||||
gamemodes: (json['gamemodes'] as List)
|
||||
.map((e) => Gamemode.fromString(e))
|
||||
.cast<Gamemode>()
|
||||
.toList(),
|
||||
screenshot: json['screenshot'],
|
||||
location: json['location'],
|
||||
countryCode: json['countryCode'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'gamemode': gamemodes.map((e) => e.toString()).toList(),
|
||||
'screenshot': screenshot,
|
||||
'location': location,
|
||||
'countryCode': countryCode,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
final class Maps {
|
||||
final Overfast _client;
|
||||
|
||||
Maps(this._client);
|
||||
|
||||
Future<List<GameMap>> maps({Gamemode? gameMode}) => _client.getList<GameMap>(
|
||||
'/maps',
|
||||
gameMode != null ? {'gamemode': gameMode.toString()} : {},
|
||||
);
|
||||
|
||||
Future<List<Gamemode>> gamemodes() async {
|
||||
// Special case, manual request
|
||||
final response = await _client.client.get(
|
||||
_client.baseUri.replace(path: '/maps/gamemodes'),
|
||||
);
|
||||
|
||||
throwIfNecessary(response.statusCode, response.body);
|
||||
|
||||
return (json.decode(response.body) as List)
|
||||
.map((e) => Gamemode.fromString(e))
|
||||
.cast<Gamemode>()
|
||||
.toList();
|
||||
}
|
||||
}
|
1
lib/overfast_api.dart
Normal file
1
lib/overfast_api.dart
Normal file
@ -0,0 +1 @@
|
||||
export 'client.dart';
|
1928
lib/players/data_types.dart
Normal file
1928
lib/players/data_types.dart
Normal file
File diff suppressed because it is too large
Load Diff
314
lib/players/player.dart
Normal file
314
lib/players/player.dart
Normal file
@ -0,0 +1,314 @@
|
||||
import 'package:overfast_api/client.dart';
|
||||
import 'package:overfast_api/utils/types.dart';
|
||||
|
||||
class PlayerSummary {
|
||||
final String username;
|
||||
final String? avatar;
|
||||
final String? namecard;
|
||||
final String? title;
|
||||
final PlayerEndorsement endorsement;
|
||||
final PlatformCompetitiveRank? competitiveRank;
|
||||
|
||||
const PlayerSummary({
|
||||
required this.username,
|
||||
this.avatar,
|
||||
this.namecard,
|
||||
this.title,
|
||||
required this.endorsement,
|
||||
required this.competitiveRank,
|
||||
});
|
||||
|
||||
factory PlayerSummary.fromJson(Map<String, dynamic> json) {
|
||||
return PlayerSummary(
|
||||
username: json['username'],
|
||||
avatar: json['avatar'],
|
||||
namecard: json['namecard'],
|
||||
title: json['title'],
|
||||
endorsement: PlayerEndorsement.fromJson(json['endorsement']),
|
||||
competitiveRank: PlatformCompetitiveRank.fromJson(json['competitive']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'username': username,
|
||||
'avatar': avatar,
|
||||
'namecard': namecard,
|
||||
'title': title,
|
||||
'endorsement': endorsement.toJson(),
|
||||
'competitiveRank': competitiveRank?.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class PlayerEndorsement {
|
||||
final int level;
|
||||
final String frame;
|
||||
|
||||
const PlayerEndorsement({
|
||||
required this.level,
|
||||
required this.frame,
|
||||
});
|
||||
|
||||
factory PlayerEndorsement.fromJson(Map<String, dynamic> json) {
|
||||
return PlayerEndorsement(
|
||||
level: json['level'],
|
||||
frame: json['frame'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'level': level,
|
||||
'frame': frame,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class PlatformCompetitiveRank {
|
||||
final CompetitiveRank? pc;
|
||||
final CompetitiveRank? console;
|
||||
|
||||
const PlatformCompetitiveRank({
|
||||
this.pc,
|
||||
this.console,
|
||||
});
|
||||
|
||||
factory PlatformCompetitiveRank.fromJson(Map<String, dynamic> json) {
|
||||
return PlatformCompetitiveRank(
|
||||
pc: json['pc'] != null ? CompetitiveRank.fromJson(json['pc']) : null,
|
||||
console: json['console'] != null
|
||||
? CompetitiveRank.fromJson(json['console'])
|
||||
: null,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'pc': pc?.toJson(),
|
||||
'console': console?.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class CompetitiveRank {
|
||||
final int season;
|
||||
final RoleDetails? tank;
|
||||
final RoleDetails? damage;
|
||||
final RoleDetails? support;
|
||||
final RoleDetails? openQueue;
|
||||
|
||||
const CompetitiveRank({
|
||||
required this.season,
|
||||
required this.tank,
|
||||
required this.damage,
|
||||
required this.support,
|
||||
required this.openQueue,
|
||||
});
|
||||
|
||||
factory CompetitiveRank.fromJson(Map<String, dynamic> json) {
|
||||
return CompetitiveRank(
|
||||
season: json['season'],
|
||||
tank: json['tank'] == null ? null : RoleDetails.fromJson(json['tank']),
|
||||
damage:
|
||||
json['damage'] == null ? null : RoleDetails.fromJson(json['damage']),
|
||||
support: json['support'] == null
|
||||
? null
|
||||
: RoleDetails.fromJson(json['support']),
|
||||
openQueue:
|
||||
json['open'] == null ? null : RoleDetails.fromJson(json['open']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'season': season,
|
||||
'tank': tank?.toJson(),
|
||||
'damage': damage?.toJson(),
|
||||
'support': support?.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class RoleDetails {
|
||||
final String division;
|
||||
final int tier;
|
||||
final String roleIcon;
|
||||
final String rankIcon;
|
||||
final String tierIcon;
|
||||
|
||||
const RoleDetails({
|
||||
required this.division,
|
||||
required this.tier,
|
||||
required this.roleIcon,
|
||||
required this.rankIcon,
|
||||
required this.tierIcon,
|
||||
});
|
||||
|
||||
factory RoleDetails.fromJson(Map<String, dynamic> json) {
|
||||
return RoleDetails(
|
||||
division: json['division'],
|
||||
tier: json['tier'],
|
||||
roleIcon: json['role_icon'],
|
||||
rankIcon: json['rank_icon'],
|
||||
tierIcon: json['tier_icon'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'division': division,
|
||||
'tier': tier,
|
||||
'roleIcon': roleIcon,
|
||||
'rankIcon': rankIcon,
|
||||
'tierIcon': tierIcon,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class StatsSummary {
|
||||
final StatsRecap general;
|
||||
final Map<String, StatsRecap> heroes;
|
||||
final Map<String, StatsRecap> roles;
|
||||
|
||||
const StatsSummary({
|
||||
required this.general,
|
||||
required this.heroes,
|
||||
required this.roles,
|
||||
});
|
||||
|
||||
factory StatsSummary.fromJson(Map<String, dynamic> json) {
|
||||
return StatsSummary(
|
||||
general: StatsRecap.fromJson(json['general']),
|
||||
heroes: Map.from(json['heroes']).map(
|
||||
(key, value) => MapEntry(key, StatsRecap.fromJson(value)),
|
||||
),
|
||||
roles: Map.from(json['roles']).map(
|
||||
(key, value) => MapEntry(key, StatsRecap.fromJson(value)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'general': general.toJson(),
|
||||
'heroes': heroes.map((key, value) => MapEntry(key, value.toJson())),
|
||||
'roles': roles.map((key, value) => MapEntry(key, value.toJson())),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class StatsRecap {
|
||||
final int gamesPlayed;
|
||||
final int gamesWon;
|
||||
final int gamesLost;
|
||||
final Duration timePlayed;
|
||||
final double winrate;
|
||||
final double kda;
|
||||
final SubStatsRecap total;
|
||||
final SubStatsRecap average;
|
||||
|
||||
const StatsRecap({
|
||||
required this.gamesPlayed,
|
||||
required this.gamesWon,
|
||||
required this.gamesLost,
|
||||
required this.timePlayed,
|
||||
required this.winrate,
|
||||
required this.kda,
|
||||
required this.total,
|
||||
required this.average,
|
||||
});
|
||||
|
||||
factory StatsRecap.fromJson(Map<String, dynamic> json) {
|
||||
return StatsRecap(
|
||||
gamesPlayed: json['games_played'],
|
||||
gamesWon: json['games_won'],
|
||||
gamesLost: json['games_lost'],
|
||||
timePlayed: Duration(seconds: json['time_played']),
|
||||
winrate: json['winrate'],
|
||||
kda: json['kda'],
|
||||
total: SubStatsRecap.fromJson(json['total']),
|
||||
average: SubStatsRecap.fromJson(json['average']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'games_played': gamesPlayed,
|
||||
'games_won': gamesWon,
|
||||
'games_lost': gamesLost,
|
||||
'time_played': timePlayed.inSeconds,
|
||||
'winrate': winrate,
|
||||
'kda': kda,
|
||||
'total': total.toJson(),
|
||||
'average': average.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class SubStatsRecap {
|
||||
final num eliminations;
|
||||
final num assists;
|
||||
final num deaths;
|
||||
final num damage;
|
||||
final num healing;
|
||||
|
||||
const SubStatsRecap({
|
||||
required this.eliminations,
|
||||
required this.assists,
|
||||
required this.deaths,
|
||||
required this.damage,
|
||||
required this.healing,
|
||||
});
|
||||
|
||||
factory SubStatsRecap.fromJson(Map<String, dynamic> json) {
|
||||
return SubStatsRecap(
|
||||
eliminations: json['eliminations'],
|
||||
assists: json['assists'],
|
||||
deaths: json['deaths'],
|
||||
damage: json['damage'],
|
||||
healing: json['healing'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'eliminations': eliminations,
|
||||
'assists': assists,
|
||||
'deaths': deaths,
|
||||
'damage': damage,
|
||||
'healing': healing,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Player {
|
||||
final String playerId;
|
||||
|
||||
final Overfast _client;
|
||||
|
||||
const Player(this._client, {required this.playerId});
|
||||
|
||||
// I.. don't know how to properly type this.
|
||||
Future<Map> career({
|
||||
Platform? platform,
|
||||
Gamemode gamemode = Gamemode.competitive,
|
||||
HeroKey? hero = HeroKey.allHeroes,
|
||||
}) {
|
||||
return _client.get<Map>(
|
||||
'/players/$playerId/stats/career',
|
||||
{
|
||||
if (platform != null) 'platform': platform.toString(),
|
||||
'gamemode': gamemode.name,
|
||||
if (hero != null) 'hero': hero.toString(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<PlayerSummary> summary() =>
|
||||
_client.get<PlayerSummary>('/players/$playerId/summary');
|
||||
|
||||
Future<StatsSummary> statsSummary() =>
|
||||
_client.get<StatsSummary>('/players/$playerId/stats/summary');
|
||||
|
||||
}
|
93
lib/players/players.dart
Normal file
93
lib/players/players.dart
Normal file
@ -0,0 +1,93 @@
|
||||
import 'package:overfast_api/client.dart';
|
||||
import 'package:overfast_api/players/player.dart';
|
||||
|
||||
class SearchResponse {
|
||||
final int total;
|
||||
final List<SearchResult> results;
|
||||
|
||||
const SearchResponse({
|
||||
required this.total,
|
||||
required this.results,
|
||||
});
|
||||
|
||||
factory SearchResponse.fromJson(Map<String, dynamic> json) {
|
||||
return SearchResponse(
|
||||
total: json['total'],
|
||||
results: (json['results'] as List)
|
||||
.map((e) => SearchResult.fromJson(e))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'total': total,
|
||||
'results': results.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class SearchResult {
|
||||
final String playerId;
|
||||
final String name;
|
||||
final String? avatar;
|
||||
final String? namecard;
|
||||
final String? title;
|
||||
final String careerUrl;
|
||||
final String blizzardId;
|
||||
|
||||
const SearchResult({
|
||||
required this.playerId,
|
||||
required this.name,
|
||||
this.avatar,
|
||||
this.namecard,
|
||||
this.title,
|
||||
required this.careerUrl,
|
||||
required this.blizzardId,
|
||||
});
|
||||
|
||||
factory SearchResult.fromJson(Map<String, dynamic> json) {
|
||||
return SearchResult(
|
||||
playerId: json['player_id'],
|
||||
name: json['name'],
|
||||
avatar: json['avatar'],
|
||||
namecard: json['namecard'],
|
||||
title: json['title'],
|
||||
careerUrl: json['career_url'],
|
||||
blizzardId: json['blizzard_id'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'playerId': playerId,
|
||||
'name': name,
|
||||
'avatar': avatar,
|
||||
'namecard': namecard,
|
||||
'title': title,
|
||||
'careerUrl': careerUrl,
|
||||
'blizzardId': blizzardId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class Players {
|
||||
final Overfast _client;
|
||||
const Players(this._client);
|
||||
|
||||
Future<SearchResponse> search(
|
||||
String query, {
|
||||
String orderBy = 'name:desc',
|
||||
int? offset,
|
||||
int? limit,
|
||||
}) async {
|
||||
return _client.get<SearchResponse>('/players', {
|
||||
'name': query,
|
||||
'orderBy': orderBy,
|
||||
if (offset != null) 'offset': offset.toString(),
|
||||
if (limit != null) 'limit': limit.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
Player player(String playerId) => Player(_client, playerId: playerId);
|
||||
}
|
76
lib/utils/get.dart
Normal file
76
lib/utils/get.dart
Normal file
@ -0,0 +1,76 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:overfast_api/heroes/heroes_data.dart';
|
||||
import 'package:overfast_api/maps/maps.dart';
|
||||
import 'package:overfast_api/players/data_types.dart';
|
||||
import 'package:overfast_api/players/player.dart';
|
||||
import 'package:overfast_api/players/players.dart';
|
||||
// import 'package:overfast_api/players/data_types.dart';
|
||||
|
||||
final fromJsonMap = <Type, Function(Map<String, dynamic>)>{
|
||||
GameMap: GameMap.fromJson,
|
||||
Map: (json) => json,
|
||||
PlayerSummary: PlayerSummary.fromJson,
|
||||
SearchResponse: SearchResponse.fromJson,
|
||||
CareerProfile: CareerProfile.fromJson,
|
||||
Hero: Hero.fromJson,
|
||||
HeroDetails: HeroDetails.fromJson,
|
||||
Roles: Roles.fromJson,
|
||||
StatsSummary: StatsSummary.fromJson,
|
||||
};
|
||||
|
||||
Future<T> Function<T>(String, [Map<String, dynamic>]) get(
|
||||
http.Client client,
|
||||
Uri baseUri,
|
||||
) {
|
||||
return <T>(
|
||||
String path, [
|
||||
Map<String, dynamic> params = const {},
|
||||
]) async {
|
||||
final uri = baseUri.replace(path: path, queryParameters: params);
|
||||
final response = await client.get(uri);
|
||||
|
||||
throwIfNecessary(response.statusCode, response.body);
|
||||
|
||||
return fromJsonMap[T]!(json.decode(response.body));
|
||||
};
|
||||
}
|
||||
|
||||
Future<List<T>> Function<T>(String, [Map<String, dynamic>])
|
||||
getList(
|
||||
http.Client client,
|
||||
Uri baseUri,
|
||||
) {
|
||||
return <T>(
|
||||
String path, [
|
||||
Map<String, dynamic> params = const {},
|
||||
]) async {
|
||||
final uri = baseUri.replace(path: path, queryParameters: params);
|
||||
final response = await client.get(uri);
|
||||
|
||||
throwIfNecessary(response.statusCode, response.body);
|
||||
|
||||
return (json.decode(response.body) as List)
|
||||
.map((e) => fromJsonMap[T]!(e)).cast<T>()
|
||||
.toList();
|
||||
};
|
||||
}
|
||||
|
||||
void throwIfNecessary(int code, String body) {
|
||||
if (code == 422) {
|
||||
throw Exception('Invalid parameters\n${json.decode(body)['detail']}');
|
||||
}
|
||||
|
||||
if (code == 500) {
|
||||
throw Exception('Internal server error');
|
||||
}
|
||||
|
||||
if (code == 504) {
|
||||
throw Exception('Blizzard Server error');
|
||||
}
|
||||
|
||||
if (code == 404) {
|
||||
throw Exception('Not found\n${json.decode(body)['error']}');
|
||||
}
|
||||
}
|
99
lib/utils/types.dart
Normal file
99
lib/utils/types.dart
Normal file
@ -0,0 +1,99 @@
|
||||
import 'utils.dart';
|
||||
|
||||
enum HeroKey {
|
||||
allHeroes,
|
||||
ana,
|
||||
ashe,
|
||||
baptiste,
|
||||
bastion,
|
||||
brigitte,
|
||||
cassidy,
|
||||
dva,
|
||||
doomfist,
|
||||
echo,
|
||||
genji,
|
||||
hanzo,
|
||||
illari,
|
||||
junkrat,
|
||||
junkerqueen('junker-queen'),
|
||||
kiriko,
|
||||
lifeweaver,
|
||||
lucio,
|
||||
mauga,
|
||||
mei,
|
||||
mercy,
|
||||
moira,
|
||||
orisa,
|
||||
pharah,
|
||||
ramattra,
|
||||
reaper,
|
||||
reinhardt,
|
||||
roadhog,
|
||||
sigma,
|
||||
sojourn,
|
||||
soldier76('soldier-76'),
|
||||
sombra,
|
||||
symmetra,
|
||||
torbjorn,
|
||||
tracer,
|
||||
widowmaker,
|
||||
winston,
|
||||
wreckingball('wrecking-ball'),
|
||||
venture,
|
||||
zarya,
|
||||
zenyatta,
|
||||
eemptyy;
|
||||
|
||||
final String? _properName;
|
||||
|
||||
const HeroKey([this._properName]);
|
||||
|
||||
String get heroName => _properName ?? name;
|
||||
|
||||
static HeroKey fromString(String value) {
|
||||
return HeroKey.values.firstWhere((e) => e.name == value || e._properName == value);
|
||||
}
|
||||
}
|
||||
|
||||
enum Locale {
|
||||
deDe,
|
||||
enGb,
|
||||
enUs,
|
||||
esEs,
|
||||
esMx,
|
||||
frFr,
|
||||
itIt,
|
||||
jaJp,
|
||||
koKr,
|
||||
plPl,
|
||||
ptBr,
|
||||
ruRu,
|
||||
zhCn;
|
||||
|
||||
@override
|
||||
String toString() => toKebabCase(name);
|
||||
|
||||
static Locale fromString(String value) {
|
||||
return Locale.values.firstWhere((e) => e.name == value);
|
||||
}
|
||||
}
|
||||
|
||||
enum Platform {
|
||||
pc,
|
||||
console,
|
||||
}
|
||||
|
||||
enum Gamemode {
|
||||
quickplay,
|
||||
competitive,
|
||||
}
|
||||
|
||||
enum Role {
|
||||
tank,
|
||||
damage,
|
||||
support;
|
||||
|
||||
static Role fromString(String value) {
|
||||
return Role.values.firstWhere((e) => e.name == value);
|
||||
}
|
||||
}
|
7
lib/utils/utils.dart
Normal file
7
lib/utils/utils.dart
Normal file
@ -0,0 +1,7 @@
|
||||
export './get.dart';
|
||||
|
||||
String toKebabCase(String text) {
|
||||
return text.replaceAllMapped(RegExp(r'([A-Z])'), (match) {
|
||||
return '-${match.group(1)?.toLowerCase()}';
|
||||
});
|
||||
}
|
66
out.json
Normal file
66
out.json
Normal file
@ -0,0 +1,66 @@
|
||||
{
|
||||
"best": {
|
||||
"eliminations_most_in_game": 56,
|
||||
"final_blows_most_in_game": 32,
|
||||
"all_damage_done_most_in_game": 27149,
|
||||
"healing_done_most_in_game": 16982,
|
||||
"defensive_assists_most_in_game": 34,
|
||||
"offensive_assists_most_in_game": 21,
|
||||
"objective_kills_most_in_game": 26,
|
||||
"objective_time_most_in_game": 355,
|
||||
"multikill_best": 4,
|
||||
"solo_kills_most_in_game": 32,
|
||||
"time_spent_on_fire_most_in_game": 98,
|
||||
"melee_final_blows_most_in_game": 8,
|
||||
"environmental_kills_most_in_game": 3,
|
||||
"kill_streak_best": 22,
|
||||
"hero_damage_done_most_in_game": 22881,
|
||||
"barrier_damage_done_most_in_game": 7789,
|
||||
"assists_most_in_game": 35,
|
||||
"objective_contest_time_most_in_game": 216,
|
||||
"recon_assists_most_in_game": 9
|
||||
},
|
||||
"average": {
|
||||
"objective_kills_avg_per_10_min": 5.71,
|
||||
"objective_time_avg_per_10_min": 77,
|
||||
"final_blows_avg_per_10_min": 8.65,
|
||||
"time_spent_on_fire_avg_per_10_min": 89,
|
||||
"objective_contest_time_avg_per_10_min": 42,
|
||||
"solo_kills_avg_per_10_min": 1.4,
|
||||
"hero_damage_done_avg_per_10_min": 7948,
|
||||
"deaths_avg_per_10_min": 6.45,
|
||||
"eliminations_avg_per_10_min": 17.39,
|
||||
"assists_avg_per_10_min": 4.69,
|
||||
"healing_done_avg_per_10_min": 1160
|
||||
},
|
||||
"game": {
|
||||
"time_played": 274097,
|
||||
"games_played": 413,
|
||||
"games_won": 219,
|
||||
"games_tied": 2,
|
||||
"games_lost": 192,
|
||||
"hero_wins": 219
|
||||
},
|
||||
"combat": {
|
||||
"environmental_kills": 63,
|
||||
"deaths": 2948,
|
||||
"objective_kills": 2608,
|
||||
"final_blows": 3950,
|
||||
"objective_time": 35000,
|
||||
"melee_final_blows": 526,
|
||||
"time_spent_on_fire": 40814,
|
||||
"eliminations": 7946,
|
||||
"objective_contest_time": 18984,
|
||||
"solo_kills": 641,
|
||||
"multikills": 59,
|
||||
"hero_damage_done": 3631039,
|
||||
"damage_done": 3631039
|
||||
},
|
||||
"assists": {
|
||||
"recon_assists": 136,
|
||||
"healing_done": 529954,
|
||||
"defensive_assists": 651,
|
||||
"offensive_assists": 377,
|
||||
"assists": 2143
|
||||
}
|
||||
}
|
389
pubspec.lock
Normal file
389
pubspec.lock
Normal file
@ -0,0 +1,389 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "67.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.4.1"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
coverage:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: coverage
|
||||
sha256: "8acabb8306b57a409bf4c83522065672ee13179297a6bb0cb9ead73948df7c76"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.7.2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_multi_server
|
||||
sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http_parser
|
||||
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: io
|
||||
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.1"
|
||||
lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: lints
|
||||
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logging
|
||||
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16+1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "25dfcaf170a0190f47ca6355bdd4552cb8924b430512ff0cafb8db9bd41fe33b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.14.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mime
|
||||
sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
node_preamble:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_preamble
|
||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.0"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pool
|
||||
sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf
|
||||
sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
shelf_packages_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_packages_handler
|
||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
shelf_static:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_static
|
||||
sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
shelf_web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shelf_web_socket
|
||||
sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
source_map_stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_map_stack_trace
|
||||
sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
source_maps:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_maps
|
||||
sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.12"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
test:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: d87214d19fb311997d8128ec501a980f77cb240ac4e7e219accf452813ff473c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.25.3"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "2419f20b0c8677b2d67c8ac4d1ac7372d862dc6c460cdbb052b40155408cd794"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.1"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "2236f70be1e5ab405c675e88c36935a87dad9e05a506b57dd5c0f617f5aebcb2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.2"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: a75f83f14ad81d5fe4b3319710b90dec37da0e22612326b696c9e1b8f34bbf48
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "14.2.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.5"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webkit_inspection_protocol
|
||||
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.3.1 <4.0.0"
|
13
pubspec.yaml
Normal file
13
pubspec.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
name: overfast_api
|
||||
description: A wrapper for the Overfast API.
|
||||
version: 0.0.1
|
||||
|
||||
environment:
|
||||
sdk: ^3.3.1
|
||||
|
||||
dependencies:
|
||||
http: ^1.2.1
|
||||
|
||||
dev_dependencies:
|
||||
lints: ^3.0.0
|
||||
test: ^1.24.0
|
47
test.ts
Normal file
47
test.ts
Normal file
@ -0,0 +1,47 @@
|
||||
type HEROES_KEYS =
|
||||
| "ana"
|
||||
| "ashe"
|
||||
| "baptiste"
|
||||
| "bastion"
|
||||
| "brigitte"
|
||||
| "cassidy"
|
||||
| "dva"
|
||||
| "doomfist"
|
||||
| "echo"
|
||||
| "genji"
|
||||
| "hanzo"
|
||||
| "junker-queen"
|
||||
| "junkrat"
|
||||
| "kiriko"
|
||||
| "lucio"
|
||||
| "mei"
|
||||
| "mercy"
|
||||
| "moira"
|
||||
| "orisa"
|
||||
| "pharah"
|
||||
| "ramattra"
|
||||
| "reaper"
|
||||
| "reinhardt"
|
||||
| "roadhog"
|
||||
| "sigma"
|
||||
| "sojourn"
|
||||
| "soldier-76"
|
||||
| "sombra"
|
||||
| "symmetra"
|
||||
| "torbjorn"
|
||||
| "tracer"
|
||||
| "widowmaker"
|
||||
| "winston"
|
||||
| "wrecking-ball"
|
||||
| "zarya"
|
||||
| "zenyatta";
|
||||
|
||||
type NEW_HEROES_KEYS<T extends string | number | symbol> = T extends HEROES_KEYS
|
||||
? HEROES_KEYS
|
||||
: T | HEROES_KEYS;
|
||||
|
||||
function fn<T extends string | number | symbol>(key: NEW_HEROES_KEYS<T>) {
|
||||
console.log(key);
|
||||
}
|
||||
|
||||
// fn('')
|
0
test/overfast_api_test.dart
Normal file
0
test/overfast_api_test.dart
Normal file
Loading…
x
Reference in New Issue
Block a user