-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test weapon configuration on the user interface
Signed-off-by: Akashdeep Dhar <[email protected]>
- Loading branch information
Showing
10 changed files
with
185 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import pytest | ||
|
||
from gi_loadouts.face.wind.main import MainWindow | ||
|
||
|
||
@pytest.fixture | ||
def runner(qtbot): | ||
testwind = MainWindow() | ||
qtbot.addWidget(testwind) | ||
return testwind |
This file was deleted.
Oops, something went wrong.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import pytest | ||
|
||
from gi_loadouts.data.weap.bows import BowsDict | ||
from gi_loadouts.type.levl import Level | ||
from gi_loadouts.type.weap import Bow, WeaponStatType | ||
from test import verify_accuracy | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"name, rare, levl, batk, seco, valu, refn", | ||
[ | ||
pytest.param("Hunter's Bow", 1, "Level 60/70 (Rank 4)", 169, WeaponStatType.none, 0, None, id="face.wind.rule: Configuring weapon - Bow - Hunter's Bow"), | ||
pytest.param("Seasoned Hunter's Bow", 2, "Level 60/70 (Rank 4)", 220, WeaponStatType.none, 0, None, id="face.wind.rule: Configuring weapon - Bow - Seasoned Hunter's Bow"), | ||
pytest.param("Recurve Bow", 3, "Level 80/90 (Rank 6)", 334, WeaponStatType.health_points_perc, 42.7, 5, id="face.wind.rule: Configuring weapon - Bow - Recurve Bow"), | ||
pytest.param("Slingshot", 3, "Level 80/90 (Rank 6)", 334, WeaponStatType.critical_rate_perc, 28.5, 5, id="face.wind.rule: Configuring weapon - Bow - Slingshot"), | ||
pytest.param("Compound Bow", 4, "Level 80/90 (Rank 6)", 427, WeaponStatType.damage_bonus_physical_perc, 62.9, 5, id="face.wind.rule: Configuring weapon - Bow - Compound Bow"), | ||
pytest.param("Favonius Warbow", 4, "Level 80/90 (Rank 6)", 427, WeaponStatType.energy_recharge_perc, 55.9, 5, id="face.wind.rule: Configuring weapon - Bow - Favonius Warbow"), | ||
pytest.param("Hamayumi", 4, "Level 80/90 (Rank 6)", 427, WeaponStatType.attack_perc, 50.3, 5, id="face.wind.rule: Configuring weapon - Bow - Hamayumi"), | ||
pytest.param("King's Squire", 4, "Level 80/90 (Rank 6)", 427, WeaponStatType.attack_perc, 50.3, 5, id="face.wind.rule: Configuring weapon - Bow - King's Squire"), | ||
pytest.param("Aqua Simulacra", 5, "Level 80/90 (Rank 6)", 506, WeaponStatType.critical_damage_perc, 80.4, 5, id="face.wind.rule: Configuring weapon - Bow - Aqua Simulacra"), | ||
pytest.param("Hunter's Path", 5, "Level 80/90 (Rank 6)", 506, WeaponStatType.critical_rate_perc, 40.2, 5, id="face.wind.rule: Configuring weapon - Bow - Hunter's Path"), | ||
pytest.param("Silvershower Heartstrings", 5, "Level 80/90 (Rank 6)", 506, WeaponStatType.health_points_perc, 60.3, 5, id="face.wind.rule: Configuring weapon - Bow - Silvershower Heartstrings"), | ||
pytest.param("Sharpshooter's Oath", 3, "Level 80/90 (Rank 6)", 375, WeaponStatType.critical_damage_perc, 42.7, 5, id="face.wind.rule: Configuring weapon - Bow - Sharpshooter's Oath"), | ||
pytest.param("Cloudforged", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.elemental_mastery, 151, 5, id="face.wind.rule: Configuring weapon - Bow - Cloudforged"), | ||
pytest.param("End of the Line", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.energy_recharge_perc, 41.9, 5, id="face.wind.rule: Configuring weapon - Bow - End of the Line"), | ||
pytest.param("Mitternachts Waltz", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.damage_bonus_physical_perc, 47.2, 5, id="face.wind.rule: Configuring weapon - Bow - Mitternachts Waltz"), | ||
pytest.param("Predator", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.attack_perc, 37.7, 1, id="face.wind.rule: Configuring weapon - Bow - Predator"), | ||
pytest.param("Prototype Crescent", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.attack_perc, 37.7, 5, id="face.wind.rule: Configuring weapon - Bow - Prototype Crescent"), | ||
pytest.param("Royal Bow", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.attack_perc, 37.7, 5, id="face.wind.rule: Configuring weapon - Bow - Royal Bow"), | ||
pytest.param("Rust", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.attack_perc, 37.7, 5, id="face.wind.rule: Configuring weapon - Bow - Rust"), | ||
pytest.param("Song of Stillness", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.attack_perc, 37.7, 5, id="face.wind.rule: Configuring weapon - Bow - Song of Stillness"), | ||
pytest.param("The Stringless", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.elemental_mastery, 151, 5, id="face.wind.rule: Configuring weapon - Bow - The Stringless"), | ||
pytest.param("The Viridescent Hunt", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.critical_rate_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Bow - The Viridescent Hunt"), | ||
pytest.param("Windblume Ode", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.elemental_mastery, 151, 5, id="face.wind.rule: Configuring weapon - Bow - Windblume Ode"), | ||
pytest.param("Amos' Bow", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.attack_perc, 45.3, 5, id="face.wind.rule: Configuring weapon - Bow - Amos' Bow"), | ||
pytest.param("Elegy for the End", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.energy_recharge_perc, 50.3, 5, id="face.wind.rule: Configuring weapon - Bow - Elegy for the End"), | ||
pytest.param("Polar Star", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.critical_rate_perc, 30.2, 5, id="face.wind.rule: Configuring weapon - Bow - Polar Star"), | ||
pytest.param("The First Great Magic", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.critical_damage_perc, 60.3, 5, id="face.wind.rule: Configuring weapon - Bow - The First Great Magic"), | ||
pytest.param("Thundering Pulse", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.critical_damage_perc, 60.3, 5, id="face.wind.rule: Configuring weapon - Bow - Thundering Pulse"), | ||
pytest.param("Alley Hunter", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.attack_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Bow - Alley Hunter"), | ||
pytest.param("Blackcliff Warbow", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.critical_damage_perc, 33.5, 5, id="face.wind.rule: Configuring weapon - Bow - Blackcliff Warbow"), | ||
pytest.param("Chain Breaker", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.attack_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Bow - Chain Breaker"), | ||
pytest.param("Fading Twilight", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.energy_recharge_perc, 27.9, 5, id="face.wind.rule: Configuring weapon - Bow - Fading Twilight"), | ||
pytest.param("Ibis Piercer", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.attack_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Bow - Ibis Piercer"), | ||
pytest.param("Mouun's Moon", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.attack_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Bow - Mouun's Moon"), | ||
pytest.param("Range Gauge", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.attack_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Bow - Range Gauge"), | ||
pytest.param("Sacrificial Bow", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.energy_recharge_perc, 27.9, 5, id="face.wind.rule: Configuring weapon - Bow - Sacrificial Bow"), | ||
pytest.param("Scion of the Blazing Sun", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.critical_rate_perc, 16.8, 5, id="face.wind.rule: Configuring weapon - Bow - Scion of the Blazing Sun"), | ||
pytest.param("Skyward Harp", 5, "Level 80/90 (Rank 6)", 621, WeaponStatType.critical_rate_perc, 20.1, 5, id="face.wind.rule: Configuring weapon - Bow - Skyward Harp"), | ||
] | ||
) | ||
def test_bow(runner, name, rare, levl, batk, seco, valu, refn) -> None: | ||
""" | ||
Test the configuration of weapons on the user interface | ||
:return: | ||
""" | ||
|
||
""" | ||
Set the user interface elements as intended | ||
""" | ||
runner.head_char_elem.setCurrentText("Anemo") | ||
runner.head_char_name.setCurrentText("Venti") | ||
unit = BowsDict[name] | ||
unit.levl = getattr(Level, levl.replace(" ", "_").replace("(", "").replace(")", "").replace("/", "_")) | ||
runner.weap_area_name.setCurrentText(name) | ||
runner.weap_area_levl.setCurrentText(levl) | ||
if isinstance(refn, int): | ||
runner.weap_area_refn.setCurrentText(f"Refinement {refn}") | ||
|
||
""" | ||
Confirm if the user interface elements change accordingly | ||
""" | ||
assert runner.weap_area_type.currentText().strip() == Bow().type.value | ||
assert " ".join(["STAR"] * unit.rare.value.qant) == runner.weap_area_rare.text() | ||
assert "ATK" == runner.weap_area_batk.text().split(" ")[0] | ||
assert verify_accuracy(round(unit.main_stat.stat_data), round(float(runner.weap_area_batk.text().split(" ")[-1]))) | ||
if unit.seco_stat.stat_name == WeaponStatType.none: | ||
assert runner.weap_area_stat.text() == "No substats" | ||
else: | ||
assert unit.seco_stat.stat_name.value.value in runner.weap_area_stat.text() | ||
assert verify_accuracy(unit.seco_stat_calc.stat_data, float(runner.weap_area_stat.text().split(" ")[-1]), 1) | ||
|
||
if isinstance(refn, int): | ||
assert runner.weap_area_refn_head.text() == f"<b>{unit.refi_name}</b>" | ||
assert runner.weap_area_refn_body.toPlainText() == unit.refi_list[refn - 1] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import pytest | ||
|
||
from gi_loadouts.data.weap.catalysts import CatalystsDict | ||
from gi_loadouts.type.levl import Level | ||
from gi_loadouts.type.weap import Catalyst, WeaponStatType | ||
from test import verify_accuracy | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"name, rare, levl, batk, seco, valu, refn", | ||
[ | ||
pytest.param("Magic Guide", 3, "Level 80/90 (Rank 6)", 334, WeaponStatType.elemental_mastery, 171, 5, id="face.wind.rule: Configuring weapon - Catalyst - Magic Guide"), | ||
pytest.param("Dodoco Tales", 4, "Level 80/90 (Rank 6)", 427, WeaponStatType.attack_perc, 50.3, 5, id="face.wind.rule: Configuring weapon - Catalyst - Dodoco Tales"), | ||
pytest.param("Eye of Perception", 4, "Level 80/90 (Rank 6)", 427, WeaponStatType.attack_perc, 50.3, 5, id="face.wind.rule: Configuring weapon - Catalyst - Eye of Perception"), | ||
pytest.param("Sacrificial Fragments", 4, "Level 80/90 (Rank 6)", 427, WeaponStatType.elemental_mastery, 201, 5, id="face.wind.rule: Configuring weapon - Catalyst - Sacrificial Fragments"), | ||
pytest.param("Sacrificial Jade", 4, "Level 80/90 (Rank 6)", 427, WeaponStatType.critical_rate_perc, 33.5, 5, id="face.wind.rule: Configuring weapon - Catalyst - Sacrificial Jade"), | ||
pytest.param("A Thousand Floating Dreams", 5, "Level 80/90 (Rank 6)", 506, WeaponStatType.elemental_mastery, 241, 5, id="face.wind.rule: Configuring weapon - Catalyst - A Thousand Floating Dreams"), | ||
pytest.param("Surf's Up", 5, "Level 80/90 (Rank 6)", 506, WeaponStatType.critical_damage_perc, 80.4, 5, id="face.wind.rule: Configuring weapon - Catalyst - Surf's Up"), | ||
pytest.param("Tome of the Eternal Flow", 5, "Level 80/90 (Rank 6)", 506, WeaponStatType.critical_damage_perc, 80.4, 5, id="face.wind.rule: Configuring weapon - Catalyst - Tome of the Eternal Flow"), | ||
pytest.param("Apprentice's Notes", 1, "Level 60/70 (Rank 4)", 169, WeaponStatType.none, 0, None, id="face.wind.rule: Configuring weapon - Catalyst - Apprentice's Notes"), | ||
pytest.param("Pocket Grimoire", 2, "Level 60/70 (Rank 4)", 220, WeaponStatType.none, 0, None, id="face.wind.rule: Configuring weapon - Catalyst - Pocket Grimoire"), | ||
pytest.param("Otherworldly Story", 3, "Level 80/90 (Rank 6)", 375, WeaponStatType.energy_recharge_perc, 35.6, 5, id="face.wind.rule: Configuring weapon - Catalyst - Otherworldly Story"), | ||
pytest.param("Thrilling Tales of Dragon Slayers", 3, "Level 80/90 (Rank 6)", 375, WeaponStatType.health_points_perc, 32.1, 5, id="face.wind.rule: Configuring weapon - Catalyst - Thrilling Tales of Dragon Slayers"), | ||
pytest.param("Ash-Graven Drinking Horn", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.health_points_perc, 37.7, 5, id="face.wind.rule: Configuring weapon - Catalyst - Ash-Graven Drinking Horn"), | ||
pytest.param("Blackcliff Agate", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.critical_damage_perc, 50.3, 5, id="face.wind.rule: Configuring weapon - Catalyst - Blackcliff Agate"), | ||
pytest.param("Favonius Codex", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.energy_recharge_perc, 41.9, 5, id="face.wind.rule: Configuring weapon - Catalyst - Favonius Codex"), | ||
pytest.param("Frostbearer", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.attack_perc, 37.7, 5, id="face.wind.rule: Configuring weapon - Catalyst - Frostbearer"), | ||
pytest.param("Fruit of Fulfillment", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.energy_recharge_perc, 41.9, 5, id="face.wind.rule: Configuring weapon - Catalyst - Fruit of Fulfillment"), | ||
pytest.param("Prototype Amber", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.health_points_perc, 37.7, 5, id="face.wind.rule: Configuring weapon - Catalyst - Prototype Amber"), | ||
pytest.param("Ring of Yaxche", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.health_points_perc, 37.7, 5, id="face.wind.rule: Configuring weapon - Catalyst - Ring of Yaxche"), | ||
pytest.param("Solar Pearl", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.critical_rate_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Catalyst - Solar Pearl"), | ||
pytest.param("The Widsith", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.critical_damage_perc, 50.3, 5, id="face.wind.rule: Configuring weapon - Catalyst - The Widsith"), | ||
pytest.param("Wandering Evenstar", 4, "Level 80/90 (Rank 6)", 475, WeaponStatType.elemental_mastery, 151, 5, id="face.wind.rule: Configuring weapon - Catalyst - Wandering Evenstar"), | ||
pytest.param("Everlasting Moonglow", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.health_points_perc, 45.3, 5, id="face.wind.rule: Configuring weapon - Catalyst - Everlasting Moonglow"), | ||
pytest.param("Jadefall's Splendor", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.health_points_perc, 45.3, 5, id="face.wind.rule: Configuring weapon - Catalyst - Jadefall's Splendor"), | ||
pytest.param("Kagura's Verity", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.critical_damage_perc, 60.3, 5, id="face.wind.rule: Configuring weapon - Catalyst - Kagura's Verity"), | ||
pytest.param("Lost Prayer to the Sacred Winds", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.critical_rate_perc, 30.2, 5, id="face.wind.rule: Configuring weapon - Catalyst - Lost Prayer to the Sacred Winds"), | ||
pytest.param("Memory of Dust", 5, "Level 80/90 (Rank 6)", 563, WeaponStatType.attack_perc, 45.3, 5, id="face.wind.rule: Configuring weapon - Catalyst - Memory of Dust"), | ||
pytest.param("Emerald Orb", 3, "Level 80/90 (Rank 6)", 415, WeaponStatType.elemental_mastery, 85, 5, id="face.wind.rule: Configuring weapon - Catalyst - Emerald Orb"), | ||
pytest.param("Twin Nephrite", 3, "Level 80/90 (Rank 6)", 415, WeaponStatType.critical_rate_perc, 14.2, 5, id="face.wind.rule: Configuring weapon - Catalyst - Twin Nephrite"), | ||
pytest.param("Ballad of the Boundless Blue", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.energy_recharge_perc, 27.9, 5, id="face.wind.rule: Configuring weapon - Catalyst - Ballad of the Boundless Blue"), | ||
pytest.param("Flowing Purity", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.attack_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Catalyst - Flowing Purity"), | ||
pytest.param("Hakushin Ring", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.energy_recharge_perc, 27.9, 5, id="face.wind.rule: Configuring weapon - Catalyst - Hakushin Ring"), | ||
pytest.param("Mappa Mare", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.elemental_mastery, 101, 5, id="face.wind.rule: Configuring weapon - Catalyst - Mappa Mare"), | ||
pytest.param("Oathsworn Eye", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.attack_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Catalyst - Oathsworn Eye"), | ||
pytest.param("Royal Grimoire", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.attack_perc, 25.1, 5, id="face.wind.rule: Configuring weapon - Catalyst - Royal Grimoire"), | ||
pytest.param("Wine and Song", 4, "Level 80/90 (Rank 6)", 523, WeaponStatType.energy_recharge_perc, 27.9, 5, id="face.wind.rule: Configuring weapon - Catalyst - Wine and Song"), | ||
pytest.param("Cashflow Supervision", 5, "Level 80/90 (Rank 6)", 621, WeaponStatType.critical_rate_perc, 20.1, 5, id="face.wind.rule: Configuring weapon - Catalyst - Cashflow Supervision"), | ||
pytest.param("Skyward Atlas", 5, "Level 80/90 (Rank 6)", 621, WeaponStatType.attack_perc, 30.2, 5, id="face.wind.rule: Configuring weapon - Catalyst - Skyward Atlas"), | ||
pytest.param("Tulaytullah's Remembrance", 5, "Level 80/90 (Rank 6)", 621, WeaponStatType.critical_damage_perc, 40.2, 5, id="face.wind.rule: Configuring weapon - Catalyst - Tulaytullah's Remembrance"), | ||
pytest.param("Crane's Echoing Call", 5, "Level 80/90 (Rank 6)", 679, WeaponStatType.attack_perc, 15.1, 5, id="face.wind.rule: Configuring weapon - Catalyst - Crane's Echoing Call"), | ||
] | ||
) | ||
def test_catalyst(runner, name, rare, levl, batk, seco, valu, refn) -> None: | ||
""" | ||
Test the configuration of weapons on the user interface | ||
:return: | ||
""" | ||
|
||
""" | ||
Set the user interface elements as intended | ||
""" | ||
runner.head_char_elem.setCurrentText("Dendro") | ||
runner.head_char_name.setCurrentText("Nahida") | ||
unit = CatalystsDict[name] | ||
unit.levl = getattr(Level, levl.replace(" ", "_").replace("(", "").replace(")", "").replace("/", "_")) | ||
runner.weap_area_name.setCurrentText(name) | ||
runner.weap_area_levl.setCurrentText(levl) | ||
if isinstance(refn, int): | ||
runner.weap_area_refn.setCurrentText(f"Refinement {refn}") | ||
|
||
""" | ||
Confirm if the user interface elements change accordingly | ||
""" | ||
assert runner.weap_area_type.currentText().strip() == Catalyst().type.value | ||
assert " ".join(["STAR"] * unit.rare.value.qant) == runner.weap_area_rare.text() | ||
assert "ATK" == runner.weap_area_batk.text().split(" ")[0] | ||
assert verify_accuracy(round(unit.main_stat.stat_data), round(float(runner.weap_area_batk.text().split(" ")[-1]))) | ||
if unit.seco_stat.stat_name == WeaponStatType.none: | ||
assert runner.weap_area_stat.text() == "No substats" | ||
else: | ||
assert unit.seco_stat.stat_name.value.value in runner.weap_area_stat.text() | ||
assert verify_accuracy(unit.seco_stat_calc.stat_data, float(runner.weap_area_stat.text().split(" ")[-1]), 1) | ||
|
||
if isinstance(refn, int): | ||
assert runner.weap_area_refn_head.text() == f"<b>{unit.refi_name}</b>" | ||
assert runner.weap_area_refn_body.toPlainText() == unit.refi_list[refn - 1] |
Empty file.
Empty file.
Empty file.