Level reward system

This commit is contained in:
Sam 2017-05-28 12:57:44 +01:00
parent 7705bd34a3
commit efdffa6272
13 changed files with 761 additions and 7 deletions

View File

@ -6,6 +6,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import mineplex.core.achievement.leveling.LevelingManager;
import mineplex.core.common.util.C;
public enum Achievement
@ -1241,7 +1242,7 @@ public enum Achievement
private static int[] getExperienceLevels()
{
int[] levels = new int[100];
int[] levels = new int[LevelingManager.MAX_LEVEL];
int expReq = 0;
@ -1275,12 +1276,36 @@ public enum Achievement
levels[i] = expReq;
}
for (int i=80 ; i<levels.length ; i++)
for (int i=80 ; i<100 ; i++)
{
expReq += 5000;
levels[i] = expReq;
}
for (int i=100 ; i<200 ; i++)
{
expReq += 6000;
levels[i] = expReq;
}
for (int i=200 ; i<300 ; i++)
{
expReq += 7000;
levels[i] = expReq;
}
for (int i=300 ; i<400 ; i++)
{
expReq += 8000;
levels[i] = expReq;
}
for (int i=400 ; i<levels.length ; i++)
{
expReq += 9000;
levels[i] = expReq;
}
return levels;
}

View File

@ -1,5 +1,6 @@
package mineplex.core.achievement;
import mineplex.core.achievement.leveling.LevelingManager;
import mineplex.core.stats.PlayerStats;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
@ -12,7 +13,6 @@ import mineplex.core.achievement.command.StatsCommand;
import mineplex.core.achievement.ui.AchievementShop;
import mineplex.core.common.Rank;
import mineplex.core.common.util.NautHashMap;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.donation.DonationManager;
import mineplex.core.elo.EloManager;
import mineplex.core.incognito.IncognitoManager;
@ -25,7 +25,7 @@ import java.util.UUID;
public class AchievementManager extends MiniPlugin
{
private static final List<String> NO_FAKE_LEVELS = Arrays.asList("samczsun");
private static final List<String> NO_FAKE_LEVELS = Arrays.asList("samczsun", "Moppletop");
private CoreClientManager _clientManager;
private IncognitoManager _incognitoManager;
@ -49,6 +49,8 @@ public class AchievementManager extends MiniPlugin
_eloManager = eloManager;
_clientManager = clientManager;
_shop = new AchievementShop(this, _statsManager, clientManager, donationManager, "Achievement");
new LevelingManager(this);
}
public AchievementData get(Player player, Achievement type)

View File

@ -0,0 +1,208 @@
package mineplex.core.achievement.leveling;
import com.google.common.collect.ImmutableMap;
import mineplex.core.MiniPlugin;
import mineplex.core.account.CoreClientManager;
import mineplex.core.achievement.Achievement;
import mineplex.core.achievement.AchievementManager;
import mineplex.core.achievement.leveling.rewards.LevelChestReward;
import mineplex.core.achievement.leveling.rewards.LevelCurrencyReward;
import mineplex.core.achievement.leveling.rewards.LevelReward;
import mineplex.core.achievement.leveling.ui.LevelRewardShop;
import mineplex.core.command.CommandBase;
import mineplex.core.common.Rank;
import mineplex.core.common.currency.GlobalCurrency;
import mineplex.core.common.util.C;
import mineplex.core.donation.DonationManager;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.treasure.TreasureType;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class LevelingManager extends MiniPlugin
{
private static final Map<Integer, LevelReward> REWARDS = ImmutableMap.<Integer, LevelReward>builder()
.put(1, new LevelCurrencyReward(GlobalCurrency.GEM, 1000))
.put(2, new LevelCurrencyReward(GlobalCurrency.GEM, 2000))
.put(3, new LevelCurrencyReward(GlobalCurrency.GEM, 3000))
.put(4, new LevelCurrencyReward(GlobalCurrency.GEM, 4000))
.put(5, new LevelChestReward(TreasureType.OLD, 1))
.put(6, new LevelCurrencyReward(GlobalCurrency.GEM, 6000))
.put(7, new LevelCurrencyReward(GlobalCurrency.GEM, 7000))
.put(100, new LevelCurrencyReward(GlobalCurrency.GEM, 1))
.put(250, new LevelChestReward(TreasureType.MYTHICAL, 1))
.put(500, new LevelChestReward(TreasureType.ILLUMINATED, 1))
.build();
// That is a big old number
public static final int MAX_LEVEL = 500;
public static final int MAX_LEVEL_MAIN_MENU = 100;
private final AchievementManager _achievement;
private final CoreClientManager _client;
private final LevelingRepository _repository;
private final Map<UUID, List<Integer>> _claimedRewards;
private final LevelRewardShop _shop;
public LevelingManager(AchievementManager achievementManager)
{
super("Level");
_achievement = achievementManager;
_client = require(CoreClientManager.class);
_repository = new LevelingRepository(this, _client);
_claimedRewards = new HashMap<>();
_shop = new LevelRewardShop(this, _client, require(DonationManager.class));
addCommand(new CommandBase<LevelingManager>(this, Rank.ALL, "level")
{
@Override
public void Execute(Player caller, String[] args)
{
_shop.attemptShopOpen(caller);
}
});
}
public void onLogin(UUID player, ResultSet resultSet)
{
List<Integer> levels = new ArrayList<>(50);
try
{
while (resultSet.next())
{
levels.add(resultSet.getInt("level"));
}
}
catch (SQLException e)
{
e.printStackTrace();
}
_claimedRewards.put(player, levels);
}
@EventHandler
public void playerJoin(PlayerJoinEvent event)
{
UUID player = event.getPlayer().getUniqueId();
// If there was no entries in the database for this player, then onLogin won't be called.
_claimedRewards.putIfAbsent(player, new ArrayList<>());
}
@EventHandler
public void playerQuit(PlayerQuitEvent event)
{
_claimedRewards.remove(event.getPlayer().getUniqueId());
}
public int getLevel(Player player)
{
return _achievement.getMineplexLevelNumber(player, Rank.ALL);
}
public int getFirstUnclaimedLevel(Player player)
{
List<Integer> claimed = _claimedRewards.get(player.getUniqueId());
for (int i = 1; i <= MAX_LEVEL; i++)
{
LevelReward reward = getLevelReward(i);
if (reward == null)
{
continue;
}
if (!claimed.contains(i))
{
return i;
}
}
return MAX_LEVEL;
}
public LevelReward getLevelReward(int level)
{
return REWARDS.get(level);
}
public ItemStack getLevelItem(Player player, LevelReward reward, int level)
{
boolean claimed = hasClaimed(player, level);
boolean canClaim = canClaim(player, level);
Material material;
byte data = 0;
String title = "Level " + Achievement.getExperienceString(level);
String bottomLine;
ItemBuilder builder = new ItemBuilder(Material.AIR);
// Already claimed
if (claimed)
{
material = Material.INK_SACK;
data = 8;
title = C.cRed + title;
bottomLine = C.cRed + "You have already claimed this reward.";
}
// Hasn't claimed and could claim
else if (canClaim)
{
material = level >= 100 ? Material.DIAMOND_BLOCK : Material.EMERALD_BLOCK;
title = C.cGreen + title;
bottomLine = C.cGreen + "Click to claim this reward.";
builder.setGlow(true);
}
// Hasn't claimed and can't claim
else
{
material = level >= 100 ? Material.OBSIDIAN : Material.REDSTONE_BLOCK;
title = C.cRed + title;
bottomLine = C.cRed + "You aren't a high enough level to claim this.";
}
builder.setType(material);
builder.setData(data);
builder.setTitle(title);
builder.addLore("", " " + reward.getDescription(), "", bottomLine);
return builder.build();
}
public void claim(Player player, int level)
{
_claimedRewards.get(player.getUniqueId()).add(level);
_repository.claimReward(_client.Get(player), level);
}
public boolean hasClaimed(Player player, int level)
{
return _claimedRewards.get(player.getUniqueId()).contains(level);
}
public boolean canClaim(Player player, int level)
{
return getLevel(player) >= level;
}
}

View File

@ -0,0 +1,58 @@
package mineplex.core.achievement.leveling;
import mineplex.core.account.CoreClient;
import mineplex.core.account.CoreClientManager;
import mineplex.core.account.ILoginProcessor;
import mineplex.serverdata.database.DBPool;
import mineplex.serverdata.database.RepositoryBase;
import mineplex.serverdata.database.column.ColumnInt;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.UUID;
public class LevelingRepository extends RepositoryBase implements ILoginProcessor
{
private static final String GET_CLAIMED_REWARDS = "SELECT level FROM accountLevelReward WHERE accountId=";
private static final String CLAIM_REWARD = "INSERT INTO accountLevelReward VALUES (?,?);";
private final LevelingManager _levelingManager;
public LevelingRepository(LevelingManager levelingManager, CoreClientManager clientManager)
{
super(DBPool.getAccount());
_levelingManager = levelingManager;
clientManager.addStoredProcedureLoginProcessor(this);
}
@Override
public String getName()
{
return "Level Rewards";
}
@Override
public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException
{
_levelingManager.onLogin(uuid, resultSet);
}
@Override
public String getQuery(int accountId, String uuid, String name)
{
return GET_CLAIMED_REWARDS + accountId + ";";
}
public void claimReward(CoreClient client, int level)
{
int accountId = client.getAccountId();
executeInsert(CLAIM_REWARD, null,
new ColumnInt("accountId", accountId),
new ColumnInt("level", level)
);
}
}

View File

@ -0,0 +1,29 @@
package mineplex.core.achievement.leveling.rewards;
import mineplex.core.treasure.TreasureType;
import org.bukkit.entity.Player;
public class LevelChestReward implements LevelReward
{
private final TreasureType _chest;
private final int _amount;
public LevelChestReward(TreasureType chest, int amount)
{
_chest = chest;
_amount = amount;
}
@Override
public void claim(Player player)
{
INVENTORY.addItemToInventory(null, player, _chest.getItemName(), 1);
}
@Override
public String getDescription()
{
return "+" + _amount + " " + _chest.getName();
}
}

View File

@ -0,0 +1,30 @@
package mineplex.core.achievement.leveling.rewards;
import mineplex.core.common.currency.GlobalCurrency;
import mineplex.core.common.util.F;
import org.bukkit.entity.Player;
public class LevelCurrencyReward implements LevelReward
{
private final GlobalCurrency _type;
private final int _amount;
public LevelCurrencyReward(GlobalCurrency type, int amount)
{
_type = type;
_amount = amount;
}
@Override
public void claim(Player player)
{
DONATION.rewardCurrencyUntilSuccess(_type, player, "Level Reward", _amount);
}
@Override
public String getDescription()
{
return "+" + F.currency(_type, _amount);
}
}

View File

@ -0,0 +1,18 @@
package mineplex.core.achievement.leveling.rewards;
import mineplex.core.Managers;
import mineplex.core.donation.DonationManager;
import mineplex.core.inventory.InventoryManager;
import org.bukkit.entity.Player;
public interface LevelReward
{
DonationManager DONATION = Managers.require(DonationManager.class);
InventoryManager INVENTORY = Managers.require(InventoryManager.class);
void claim(Player player);
String getDescription();
}

View File

@ -0,0 +1,24 @@
package mineplex.core.achievement.leveling.ui;
import mineplex.core.account.CoreClientManager;
import mineplex.core.achievement.leveling.LevelingManager;
import mineplex.core.achievement.leveling.ui.page.LevelRewardMainPage;
import mineplex.core.donation.DonationManager;
import mineplex.core.shop.ShopBase;
import mineplex.core.shop.page.ShopPageBase;
import org.bukkit.entity.Player;
public class LevelRewardShop extends ShopBase<LevelingManager>
{
public LevelRewardShop(LevelingManager plugin, CoreClientManager clientManager, DonationManager donationManager)
{
super(plugin, clientManager, donationManager, "Level Reward");
}
@Override
protected ShopPageBase<LevelingManager, ? extends ShopBase<LevelingManager>> buildPagesFor(Player player)
{
return new LevelRewardMainPage(getPlugin(), this, getClientManager(), getDonationManager(), player);
}
}

View File

@ -0,0 +1,50 @@
package mineplex.core.achievement.leveling.ui.button;
import mineplex.core.achievement.leveling.LevelingManager;
import mineplex.core.achievement.leveling.rewards.LevelReward;
import mineplex.core.achievement.leveling.ui.LevelRewardShop;
import mineplex.core.achievement.leveling.ui.page.LevelRewardMainPage;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.shop.item.IButton;
import mineplex.core.shop.page.ShopPageBase;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
public class LevelRewardButton implements IButton
{
private LevelingManager _plugin;
private ShopPageBase<LevelingManager, LevelRewardShop> _menu;
private final LevelReward _reward;
private final int _level;
public LevelRewardButton(ShopPageBase<LevelingManager, LevelRewardShop> menu, LevelReward reward, int level)
{
_plugin = menu.getPlugin();
_menu = menu;
_reward = reward;
_level = level;
}
@Override
public void onClick(Player player, ClickType clickType)
{
if (_plugin.hasClaimed(player, _level) || !_plugin.canClaim(player, _level))
{
_menu.playDenySound(player);
return;
}
// Give the player the reward
_reward.claim(player);
_plugin.claim(player, _level);
// Give some feedback
_menu.playAcceptSound(player);
player.sendMessage(F.main(_plugin.getName(), "You claimed " + _reward.getDescription() + C.mBody + "."));
// Rebuild the menu
_menu.refresh();
}
}

View File

@ -0,0 +1,83 @@
package mineplex.core.achievement.leveling.ui.page;
import mineplex.core.account.CoreClientManager;
import mineplex.core.achievement.leveling.LevelingManager;
import mineplex.core.achievement.leveling.rewards.LevelReward;
import mineplex.core.achievement.leveling.ui.LevelRewardShop;
import mineplex.core.achievement.leveling.ui.button.LevelRewardButton;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilInv;
import mineplex.core.common.util.UtilUI;
import mineplex.core.donation.DonationManager;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.shop.item.IButton;
import mineplex.core.shop.page.ShopPageBase;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class LevelRewardExclusivePage extends ShopPageBase<LevelingManager, LevelRewardShop>
{
private static final ItemStack GO_BACK = new ItemBuilder(Material.BED)
.setTitle(C.cGreen + "Click to go back.")
.build();
private static final ItemStack MAXED = new ItemBuilder(Material.FIREWORK)
.setTitle(C.cPurpleB + "Congratulations")
.addLore("You have reached the maximum", "level possible, you must really love Mineplex!", "From all of us here at Mineplex we'd like to thank you", "for putting the in crazy number of hours to achieve this", "Unless you are an admin, in which you cheated", C.cPurple + "<3")
.build();
private static final int[] MAPPINGS = {
10, 11, 12, 13, 14, 15, 16,
19, 20, 21, 22, 23, 24, 25,
28, 29, 30, 31, 32, 33, 34
};
private ShopPageBase<LevelingManager, LevelRewardShop> _menu;
public LevelRewardExclusivePage(LevelingManager plugin, LevelRewardShop shop, ShopPageBase<LevelingManager, LevelRewardShop> menu, CoreClientManager clientManager, DonationManager donationManager, Player player)
{
super(plugin, shop, clientManager, donationManager, "Exclusive Level Rewards", player);
_menu = menu;
buildPage();
}
@Override
protected void buildPage()
{
int level = _plugin.getLevel(_player);
int menuIndex = 0;
for (int i = LevelingManager.MAX_LEVEL_MAIN_MENU; i <= LevelingManager.MAX_LEVEL; i++)
{
LevelReward reward = _plugin.getLevelReward(i);
if (reward == null)
{
continue;
}
addButton(MAPPINGS[menuIndex++], _plugin.getLevelItem(_player, reward, i), new LevelRewardButton(this, reward, i));
}
// This would occur if the max level was reached and claimed
if (level == LevelingManager.MAX_LEVEL && _plugin.hasClaimed(_player, level))
{
addButtonNoAction(41, MAXED);
}
addButton(49, GO_BACK, new GoBackButton());
}
private class GoBackButton implements IButton
{
@Override
public void onClick(Player player, ClickType clickType)
{
_shop.openPageForPlayer(player, _menu);
}
}
}

View File

@ -0,0 +1,106 @@
package mineplex.core.achievement.leveling.ui.page;
import mineplex.core.account.CoreClientManager;
import mineplex.core.achievement.leveling.LevelingManager;
import mineplex.core.achievement.leveling.rewards.LevelReward;
import mineplex.core.achievement.leveling.ui.LevelRewardShop;
import mineplex.core.achievement.leveling.ui.button.LevelRewardButton;
import mineplex.core.common.util.C;
import mineplex.core.donation.DonationManager;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.shop.item.IButton;
import mineplex.core.shop.page.ShopPageBase;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class LevelRewardMainPage extends ShopPageBase<LevelingManager, LevelRewardShop>
{
private static final int MID_INDEX = 13;
private static final int VIEW_ALL_INDEX = 22;
private static final ItemStack VIEW_ALL = new ItemBuilder(Material.BOOK)
.setTitle(C.cGreen + "View All Rewards")
.addLore("Click to view all rewards.")
.build();
private static final ItemStack EXCLUSIVE = new ItemBuilder(Material.DIAMOND_BLOCK)
.setTitle(C.cAquaB + "Exclusive Rewards")
.addLore("", "Click to view the exclusive rewards", "for players who have reached level 100+!")
.build();
public LevelRewardMainPage(LevelingManager plugin, LevelRewardShop shop, CoreClientManager clientManager, DonationManager donationManager, Player player)
{
super(plugin, shop, clientManager, donationManager, "Level Rewards", player, 3 * 9);
buildPage();
}
@Override
protected void buildPage()
{
int level = _plugin.getFirstUnclaimedLevel(_player);
int start = level - 2;
int end = level + 2;
int menuIndex = MID_INDEX - 2;
int currentLevel = start;
for (int i = start; i <= end; )
{
if (i <= 0)
{
i++;
menuIndex++;
currentLevel++;
continue;
}
if (currentLevel >= LevelingManager.MAX_LEVEL_MAIN_MENU)
{
addButton(level >= LevelingManager.MAX_LEVEL_MAIN_MENU ? MID_INDEX : menuIndex, EXCLUSIVE, new ExclusiveRewardsButton());
break;
}
LevelReward reward = _plugin.getLevelReward(currentLevel);
if (reward == null)
{
currentLevel++;
continue;
}
addButton(menuIndex++, _plugin.getLevelItem(_player, reward, currentLevel), new LevelRewardButton(this, reward, currentLevel));
i++;
currentLevel++;
}
addButton(VIEW_ALL_INDEX, VIEW_ALL, new ViewAllRewardsButton());
}
private class ViewAllRewardsButton implements IButton
{
@Override
public void onClick(Player player, ClickType clickType)
{
_shop.openPageForPlayer(player, new LevelRewardViewAllPage(getPlugin(), getShop(), LevelRewardMainPage.this, getClientManager(), getDonationManager(), player, 1));
}
}
private class ExclusiveRewardsButton implements IButton
{
@Override
public void onClick(Player player, ClickType clickType)
{
if (_plugin.getLevel(player) < LevelingManager.MAX_LEVEL_MAIN_MENU)
{
playDenySound(player);
return;
}
_shop.openPageForPlayer(player, new LevelRewardExclusivePage(getPlugin(), getShop(), LevelRewardMainPage.this, getClientManager(), getDonationManager(), player));
}
}
}

View File

@ -0,0 +1,119 @@
package mineplex.core.achievement.leveling.ui.page;
import mineplex.core.account.CoreClientManager;
import mineplex.core.achievement.leveling.LevelingManager;
import mineplex.core.achievement.leveling.rewards.LevelReward;
import mineplex.core.achievement.leveling.ui.LevelRewardShop;
import mineplex.core.achievement.leveling.ui.button.LevelRewardButton;
import mineplex.core.common.util.C;
import mineplex.core.donation.DonationManager;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.shop.item.IButton;
import mineplex.core.shop.page.ShopPageBase;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
public class LevelRewardViewAllPage extends ShopPageBase<LevelingManager, LevelRewardShop>
{
public static final int DISPLAY_SIZE = 45;
private static final ItemStack GO_BACK = new ItemBuilder(Material.BED)
.setTitle(C.cGreen + "Click to go back.")
.build();
private ShopPageBase<LevelingManager, LevelRewardShop> _menu;
private int _startingLevel;
public LevelRewardViewAllPage(LevelingManager plugin, LevelRewardShop shop, ShopPageBase<LevelingManager, LevelRewardShop> menu, CoreClientManager clientManager, DonationManager donationManager, Player player, int startingLevel)
{
super(plugin, shop, clientManager, donationManager, "All Level Rewards", player);
_menu = menu;
_startingLevel = startingLevel;
buildPage();
}
@Override
protected void buildPage()
{
int level = _startingLevel;
boolean lastPage = false;
// No i++ ?! look down
for (int i = 0; i < DISPLAY_SIZE; )
{
if (level >= LevelingManager.MAX_LEVEL_MAIN_MENU)
{
lastPage = true;
break;
}
LevelReward reward = _plugin.getLevelReward(level);
// No reward for that level
if (reward == null)
{
level++;
continue;
}
addButton(i++, _plugin.getLevelItem(_player, reward, level), new LevelRewardButton(this, reward, level));
level++;
}
// Not the first page
if (_startingLevel > 1)
{
addButton(46, getChangePageItem(true), new LevelRewardChangePageButton(_startingLevel - DISPLAY_SIZE));
}
// Not the last page
else if (!lastPage)
{
addButton(53, getChangePageItem(false), new LevelRewardChangePageButton(_startingLevel + DISPLAY_SIZE));
}
addButton(49, GO_BACK, new GoBackButton());
}
private ItemStack getChangePageItem(boolean previous)
{
ItemBuilder builder = new ItemBuilder(Material.SIGN);
builder.setTitle(C.cYellow + (previous ? "Previous Page" : "Next Page"));
return builder.build();
}
private class LevelRewardChangePageButton implements IButton
{
private int _newStartingIndex;
LevelRewardChangePageButton(int newStartingIndex)
{
_newStartingIndex = newStartingIndex;
}
@Override
public void onClick(Player player, ClickType clickType)
{
// Update the starting index and rebuild the page
_startingLevel = _newStartingIndex;
refresh();
}
}
private class GoBackButton implements IButton
{
@Override
public void onClick(Player player, ClickType clickType)
{
_shop.openPageForPlayer(player, _menu);
}
}
}

View File

@ -1,5 +1,7 @@
package mineplex.core.stats.command;
import mineplex.core.achievement.leveling.LevelingManager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import mineplex.core.achievement.Achievement;
@ -44,13 +46,13 @@ public class SetLevelCommand extends CommandBase<StatsManager>
return;
}
if (level < 0 || level > 100)
if (level < 0 || level > LevelingManager.MAX_LEVEL)
{
UtilPlayer.message(caller, F.main("Stats", "That level is invalid"));
return;
}
int amountNeeded = 0;
long amountNeeded = 0;
for (int i = 0; i < level; i++)
{