问:
Game Database Design
It's been awhile since my last post but I have decided to move on with trying my hand at game development. So right now something I am looking at is actual data storage. Probably not something that will be used while the game is necessarily running but on load, save and exit use.. Probably. Fact is I'm not sure yet. However, that is not the question of the hour for me. The real question I am facing is in a database design aspect. I can't for some reason wrap my head around how to design the items portion of the database. I am looking to do something efficient yet robust. Let me give some things I am reflecting on..

Assuming that this is a Fantasy RPG even possibly MMO (though that part is not important)

Trying to keep the OOP approach to this.

Now the questions:

If an Item can be multiple things (i.e. a potion/food (which I get consumables), a sword/staff (weapons)) what would be the database approach to this?

Going as an add on to the above question... So a Sword can have different specs.. depending on Material based specs (base stats) to the potential augment based stats (buffs or debuffs).. How can I encapsulate that in the database without every single item needing that information there too. (Idea being if it isn't important to this item then don't include it at all.

I am thinking the idea to this is.. if the item has a fire augment then in a table (probably some sort of junction table) define the:

StatID: primary key for this stat
Item_ID: the item being affected
Augment_ID: augment i.e. fire damage
AugmentEffect: would be +/- value

If someone can shed light on this would be great or... if someone knows a great location to find this information.

I have attempted to look through the search.. sadly I don't know what to exactly search for that returns useful results to this topic and genre. Thanks in advance.

~ Edit 1 ~
This is kinda the approach I was thinking towards segregating the different types of "items" this way based on a flag is which table to look at. Would this work in practice?

答:
Alright, for my implementation, I wanted to store various item types, this included Weapons, Apparel, Items, GameEvents, LootTables, Abilities, etc. I didnt want to use a large amount of polymorphism, because I consider it to be a weakness in a large system, especially the one that my game has become. As you can imagine, this would make a database mechanism for non-polymorphic items very difficult to create.

What I ended up doing was having a static GameDatabase class, which is initialized at runtime, loaded from a directory, and used throughout the entire game engine without having to pass around references to the Database. The Database consists of one List of each item type, and an associated enumeration, which is combined with the index of the item to create a pseudo bitmask key. The key is a single integer. What this means is that now we can pass around an integer ID for everything in the game, instead of the item itself.

Here is an example of my GameDatabase with the file loading trimmed out. I am also using C# because I absolutely abhor Java.

```<code>using System;
using System.Collections.Generic;
using VoidwalkerEngine.Framework.Collections;
using VoidwalkerEngine.Framework.DataTypes;
using VoidwalkerEngine.Framework.Entities;
using VoidwalkerEngine.Framework.Game.Items;
using VoidwalkerEngine.Framework.Rendering.OpenGL.Modeling;

namespace VoidwalkerEngine.Framework.Game.Managers
{

    public enum DatabaseLocation
    {
        Abilities,
        Apparel,
        Actors,
        Classes,
        Events,
        Items,
        LootTables,
        LootTablePools,
        Models,
        Sounds,
        StatusEffects,
        Weapons
    }

    public static class GameDatabase
    {

        public static List<Ability> Abilities;
        public static List<Actor> Actors;
        public static List<Birthsign> Classes;
        public static List<GameEvent> Events;
        public static List<GameItem> Items;
        public static List<Weapon> Weapons;
        public static List<Apparel> Apparel;
        public static List<LootTable> LootTables;
        public static List<LootTablePool> LootPools;
        public static List<VoidwalkerModel> Models;
        public static List<GameSound> Sounds;
        public static List<StatusEffect> StatusEffects;

        public static void Create()
        {
            Abilities = new List<Ability>();
            Actors = new List<Actor>();
            Classes = new List<Birthsign>();
            Events = new List<GameEvent>();
            Items = new List<GameItem>();
            Weapons = new List<Weapon>();
            Apparel = new List<Apparel>();
            LootTables = new List<LootTable>();
            LootPools = new List<LootTablePool>();
            Models = new List<VoidwalkerModel>();
            Sounds = new List<GameSound>();
            StatusEffects = new List<StatusEffect>();
        }

        public static void Initialize(int identifier)
        {
            Initialize(new DatabaseKey(identifier));
        }

        /// <summary>
        /// Initializes the Database location with a new Object of that type.
        /// The identifier for the object is automatically added.
        /// </summary>
        /// <param name="key"></param>
        public static void Initialize(DatabaseKey key)
        {
            int identifier = key.Identifier;
            int index = key.Index;
            switch (key.Location)
            {
                case DatabaseLocation.Abilities:
                    Abilities[index] = new Ability(identifier);
                    break;
                case DatabaseLocation.Apparel:
                    Apparel[index] = new Apparel(identifier);
                    break;
                case DatabaseLocation.Actors:
                    Actors[index] = new Actor(identifier);
                    break;
                case DatabaseLocation.Classes:
                    Classes[index] = new Birthsign(identifier);
                    break;
                case DatabaseLocation.Events:
                    Events[index] = new GameEvent(identifier);
                    break;
                case DatabaseLocation.Items:
                    Items[index] = new GameItem(identifier);
                    break;
                case DatabaseLocation.LootTables:
                    LootTables[index] = new LootTable(identifier);
                    break;
                case DatabaseLocation.LootTablePools:
                    LootPools[index] = new LootTablePool(identifier);
                    break;
                case DatabaseLocation.Models:
                    Models[index] = new VoidwalkerModel(identifier);
                    break;
                case DatabaseLocation.Sounds:
                    Sounds[index] = new GameSound(identifier);
                    break;
                case DatabaseLocation.StatusEffects:
                    StatusEffects[index] = new StatusEffect(identifier);
                    break;
                case DatabaseLocation.Weapons:
                    Weapons[index] = new Weapon(identifier);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        public static object Query(int identifier)
        {
            return Query(new DatabaseKey(identifier));
        }

        public static object Query(DatabaseKey key)
        {
            int index = key.Index;
            switch (key.Location)
            {
                case DatabaseLocation.Abilities:
                    return Abilities[index];
                case DatabaseLocation.Apparel:
                    return Apparel[index];
                case DatabaseLocation.Actors:
                    return Actors[index];
                case DatabaseLocation.Classes:
                    return Classes[index];
                case DatabaseLocation.Events:
                    return Events[index];
                case DatabaseLocation.Items:
                    return Items[index];
                case DatabaseLocation.LootTables:
                    return LootTables[index];
                case DatabaseLocation.LootTablePools:
                    return LootPools[index];
                case DatabaseLocation.Models:
                    return Models[index];
                case DatabaseLocation.Sounds:
                    return Sounds[index];
                case DatabaseLocation.StatusEffects:
                    return StatusEffects[index];
                case DatabaseLocation.Weapons:
                    return Weapons[index];
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
}
</code>```

In order to access an item in the database, you need to use this class to create a key for said item:

```<code>using System;
using VoidwalkerEngine.Framework.Game.Managers;

namespace VoidwalkerEngine.Framework.DataTypes
{
    public struct DatabaseKey : IEquatable<DatabaseKey>
    {
        #region Fields
        /// <summary>
        /// The Location within the Database
        /// </summary>
        public DatabaseLocation Location { get; }

        /// <summary>
        /// The Index of the Database List
        /// </summary>
        public int Index { get; }

        /// <summary>
        /// The Packed Identifier of this DatabaseKey
        /// </summary>
        public int Identifier
        {
            get
            {
                return Pack(Location, Index);
            }
        }
        #endregion

        #region Constants
        /// <summary>
        /// The Masking Multiplier. This is 10,000
        /// which means the maximum number of Items,
        /// Weapons,Apparel, etc are 9,999 for each
        /// Database List. If this number is increased
        /// it will also increase the maximum number of items.
        /// MaskMultiplier = 100,000 > 99,999 maximum items.
        /// </summary>
        public const int MaskMultiplier = 10000;
        public const int MinimumIndex = 0;
        public const int MaximumIndex = MaskMultiplier - 1;
        #endregion

        #region Constructors
        public DatabaseKey(string hexString) : this(Convert.ToInt32(hexString, 16)) { }
        public DatabaseKey(int identifier) : this(UnpackLocation(identifier), UnpackIndex(identifier)) { }
        public DatabaseKey(DatabaseKey other) : this(other.Location, other.Index) { }
        public DatabaseKey(DatabaseLocation location, int index)
        {
            this.Location = location;
            this.Index = index;
        }
        #endregion

        #region Functions
        /// <summary>
        /// Unpacks the Location from a packed HexCode.
        /// </summary>
        /// <param name="hexCode"></param>
        /// <returns></returns>
        public static DatabaseLocation UnpackLocation(int hexCode)
        {
            return (DatabaseLocation)(hexCode / MaskMultiplier);
        }

        /// <summary>
        /// Unpacks the Index within a packed HexCode.
        /// </summary>
        /// <param name="hexCode"></param>
        /// <returns></returns>
        public static int UnpackIndex(int hexCode)
        {
            return ((hexCode - ((hexCode / MaskMultiplier) * MaskMultiplier)) - 1);
        }

        /// <summary>
        /// Packs a Location and Index into an Identifier.
        /// </summary>
        /// <param name="location"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static int Pack(DatabaseLocation location, int index)
        {
            return ((((int)location * MaskMultiplier) + index) + 1);
        }
        #endregion

        #region Overrides
        public bool Equals(DatabaseKey other)
        {
            return Identifier == other.Identifier;
        }

        public override bool Equals(object obj)
        {
            return obj is DatabaseKey reference && Equals(reference);
        }

        public override int GetHashCode()
        {
            return Identifier;
        }

        public override string ToString()
        {
            return "0x" + Identifier.ToString("X");
        }
        #endregion
    }
}
</code>```

The DatabaseKey is declared as an immutable struct. In order to create a key for an item you do something like:

```<code>DatabaseKey key = new DatabaseKey(DatabaseLocation.Items,24);
</code>```

This results in an Integer identifier of: 50025 or in hex: 0xC369. What that means is that basic game items are located within the range of 50000-59999. So you take 50,000 + array index. This gives us a single integer in which to map items. Passing items around internally would then use an ItemStack implementation; here is mine:

```<code>using System;
using VoidwalkerEngine.Framework.Maths;

namespace VoidwalkerEngine.Framework.DataTypes
{
    [Serializable]
    public class ItemStack
    {

        /// <summary>
        /// The ID of the Associated Item.
        /// </summary>
        public int Identifier { get; set; }

        private int _quantity;

        /// <summary>
        /// The Quantity of this ItemStack.
        /// </summary>
        public int Quantity
        {
            get
            {
                return _quantity;
            }
            set
            {
                this._quantity = VoidwalkerMath.Clamp(value, MinQuantity, MaxQuantity);
            }
        }

        private int _maxQuantity = Int32.MaxValue;

        /// <summary>
        /// The Maximum Quantity of this Stack.
        /// </summary>
        public int MaxQuantity
        {
            get
            {
                return _maxQuantity;
            }
            set
            {
                this._maxQuantity = VoidwalkerMath.Clamp(value, MinQuantity, Int32.MaxValue);
                this.Quantity = this.Quantity;
            }
        }

        public const int MinQuantity = 0;

        public bool IsStackable
        {
            get
            {
                return this.MaxQuantity != 1;
            }
        }

        /// <summary>
        ///
        /// </summary>
        public bool IsEmpty
        {
            get
            {
                return this.Quantity == MinQuantity;
            }
        }

        /// <summary>
        ///
        /// </summary>
        public bool IsFull
        {
            get
            {
                return this.Quantity == this.MaxQuantity;
            }
        }

        public ItemStack()
        {

        }

        public ItemStack(int identifier, int quantity = 1, int maxQuantity = Int32.MaxValue)
        {
            this.Identifier = identifier;
            this.Quantity = quantity;
            this.MaxQuantity = maxQuantity;
        }

        /// <summary>
        /// Adds the specified quantity to this ItemStack. If
        /// the ItemStack is already full or close to being full,
        /// this ItemStack will overflow into a new ItemStack as the
        /// return value.
        /// </summary>
        /// <param name="quantity"></param>
        /// <returns></returns>
        public ItemStack Add(int quantity)
        {
            if (quantity <= MinQuantity)
            {
                return null;
            }
            int overflow = ComputeOverflow(quantity);
            if (overflow > MinQuantity)
            {
                this.Quantity += quantity;
                return new ItemStack(this.Identifier, overflow, this.MaxQuantity);
            }
            this.Quantity += quantity;
            return null;
        }

        /// <summary>
        /// Adds the specified quantity to this ItemStack. If
        /// the ItemStack is already full or close to being full,
        /// this ItemStack will overflow into a new ItemStack as the
        /// return value.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public ItemStack Add(ItemStack other)
        {
            ItemStack stack = Add(other.Quantity);
            other.Subtract(other.Quantity);
            return stack;
        }

        /// <summary>
        /// Subtracts the specified quantity from this ItemStack. If
        /// the ItemStack is already empty or close to being empty,
        /// this ItemStack will underflow into a new ItemStack as the
        /// return value.
        /// </summary>
        /// <param name="quantity"></param>
        /// <returns></returns>
        public ItemStack Subtract(int quantity)
        {
            if (quantity <= MinQuantity)
            {
                return null;
            }
            int underflow = ComputeUnderflow(quantity);
            if (underflow > MinQuantity)
            {
                this.Quantity -= (quantity - underflow);
            }
            this.Quantity -= quantity;
            return new ItemStack(this.Identifier, quantity, this.MaxQuantity);
        }

        /// <summary>
        /// Subtracts the specified quantity from this ItemStack. If
        /// the ItemStack is already empty or close to being empty,
        /// this ItemStack will underflow into a new ItemStack as the
        /// return value.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public ItemStack Subtract(ItemStack other)
        {
            ItemStack stack = Subtract(other.Quantity);
            other.Subtract(stack.Quantity);
            return stack;
        }

        /// <summary>
        /// Clears the Quantity of this ItemStack to 0. MaxValue, however, remains the same.
        /// </summary>
        public void Clear()
        {
            this._quantity = MinQuantity;
        }

        /// <summary>
        /// Makes the currect Quantity of this ItemStack equal to the MaxValue of this ItemStack.
        /// </summary>
        public void Fill()
        {
            this._quantity = MaxQuantity;
        }

        /// <summary>
        /// Splits this ItemStack into another, giving half to both stacks.
        /// If the split amount is an odd number, the result gets +1 so no
        /// loss of items happens due to rounding errors.
        /// </summary>
        /// <returns></returns>
        public ItemStack Split()
        {
            if (this.Quantity <= (MinQuantity + 1))
            {
                return null; // A split is impossible.
            }
            int splitResult = (this.Quantity / 2);
            if (this.Quantity % 2 == 0)
            {
                this.Quantity = splitResult;
                return new ItemStack(this.Identifier, splitResult, this.MaxQuantity);
            }
            this.Quantity = splitResult;
            return new ItemStack(this.Identifier, splitResult + 1, this.MaxQuantity);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="other"></param>
        public void Copy(ItemStack other)
        {
            this.Identifier = other.Identifier;
            this.Quantity = other.Quantity;
            this.MaxQuantity = other.MaxQuantity;
        }

        /// <summary>
        /// Creates a new ItemStack which is an exact copy of this ItemStack.
        /// </summary>
        /// <returns></returns>
        public ItemStack MakeCopy()
        {
            return new ItemStack(this.Identifier, this.Quantity, this.MaxQuantity);
        }

        /// <summary>
        /// Determines if this ItemStack is stackable with another ItemStack. This function tests
        /// for a match between the string Identifiers, and whether or not this ItemStack is Stackable.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool IsStackableWith(ItemStack other)
        {
            return this.Identifier == other.Identifier && this.IsStackable;
        }

        /// <summary>
        /// Calculates the amount of overflow that will take place
        /// if the desired ItemStack is added to this one.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int ComputeOverflow(ItemStack other)
        {
            return ComputeOverflow(other.Quantity);
        }

        /// <summary>
        /// Calculates the amount of overflow that will take place
        /// if the desired amount is added to this one.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public int ComputeOverflow(int amount)
        {
            if (amount <= MinQuantity)
            {
                return MinQuantity;
            }
            int total = ((this.Quantity + amount) - this.MaxQuantity);
            if (total < MinQuantity)
            {
                return MinQuantity;
            }
            return total;
        }

        /// <summary>
        /// Calculates the amount of underflow that will take place
        /// if the desired ItemStack is subtracted from this one.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int ComputeUnderflow(ItemStack other)
        {
            return ComputeUnderflow(other.Quantity);
        }

        /// <summary>
        /// Calculates the amount of underflow that will take place
        /// if the desired amount is subtracted from this one.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public int ComputeUnderflow(int amount)
        {
            if (amount <= MinQuantity)
            {
                return MinQuantity;
            }
            int total = (this.Quantity - amount);
            if (total > MinQuantity)
            {
                return MinQuantity;
            }
            return Math.Abs(total);
        }

        /// <summary>
        /// Determines if this ItemStack has the specified quantity.
        /// If the quantity is less than or equal to 0, this function
        /// will always return false.
        /// </summary>
        /// <param name="quantity"></param>
        /// <returns></returns>
        public bool HasQuantity(int quantity)
        {
            if (quantity <= MinQuantity)
            {
                return false;
            }
            return this.Quantity >= quantity;
        }

        /// <summary>
        /// Determines if this ItemStack can still fit the specified amount
        /// without overflowing into a new ItemStack. If the quantity is less
        /// than or equal to 0, this function will always return false.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool CanHold(ItemStack other)
        {
            return CanHold(other.Quantity);
        }

        /// <summary>
        /// Determines if this ItemStack can still fit the specified amount
        /// without overflowing into a new ItemStack. If the quantity is less
        /// than or equal to 0, this function will always return false.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public bool CanHold(int amount)
        {
            if (amount <= MinQuantity)
            {
                return false;
            }
            return this.Quantity + amount <= MaxQuantity;
        }

        /// <summary>
        /// Determines if this ItemStack can subtract the specified amount
        /// without underflowing into a new ItemStack. If the quantity is less
        /// than or equal to 0, this function will always return false.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool CanSubtract(ItemStack other)
        {
            return CanSubtract(other.Quantity);
        }

        /// <summary>
        /// Determines if this ItemStack can subtract the specified amount
        /// without underflowing into a new ItemStack. If the quantity is less
        /// than or equal to 0, this function will always return false.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public bool CanSubtract(int amount)
        {
            if (amount <= MinQuantity)
            {
                return false;
            }
            return this.Quantity - amount >= MinQuantity;
        }

        public bool Equals(ItemStack other)
        {
            if (other != null)
            {
                return
                    this.Identifier == other.Identifier &&
                    this.Quantity == other.Quantity &&
                    this.MaxQuantity == other.MaxQuantity;
            }
            return false;
        }

        public override string ToString()
        {
            return $"{this.Identifier},{this.Quantity},{this.MaxQuantity}";
        }
    }
}
</code>```

For more information on this ItemStack implementation, please see another answer I posted here: https://gamedev.stackexchange.com/questions/133000/how-do-inventories-work/133024

We do not pass around items. We pass around the integer ID's. This means we don't need to do any fancy polymorphism at all. When you need to get an item from the database, you just feed in the ID, use the location to cast it to the correct item(or other things that can achieve the cast on a dynamic level) and there you have it. This system also allows dynamic item generation. All you have to do is add another database List for Procedural Weapons, or Apparel. In the game when you augment an item, you're really just creating a new item, adding it to a list in the Database, removing the associated ItemStack from the players inventory, and then adding the new ItemStack with the new generated ID, which points to the created item in the database.

And finally, I believe a picture is worth a thousand words, so here is a screenshot of my engine using the Database system I have mentioned:

It should also be noted that this system scales very well with SQLite databases for actual storage and retrieval later down the road in your development. Essentially, you can rewrite the Database class that I have shown you to be a Query-Cache facade. So you first test to see if the item has been queried from the SQLite file already, and if it has, you just return the copy that you have already queried, else you query the item, cache it in the in-memory database, and then return it. This can greatly speed up your performance. The internal SQLite database is also very good at handling your custom integer indexes. All you would need to do for that is have a table in the SQLite file for each item type, then use the DatabaseKey struct to find out what type of item you're after, then use that to select the table from the SQLite file.

If you have any questions, I would be happy to answer them.

Title: Game Database Design

Body:
Alright, for my implementation, I wanted to store various item types, this included Weapons, Apparel, Items, GameEvents, LootTables, Abilities, etc. I didnt want to use a large amount of polymorphism, because I consider it to be a weakness in a large system, especially the one that my game has become. As you can imagine, this would make a database mechanism for non-polymorphic items very difficult to create.

What I ended up doing was having a static GameDatabase class, which is initialized at runtime, loaded from a directory, and used throughout the entire game engine without having to pass around references to the Database. The Database consists of one List of each item type, and an associated enumeration, which is combined with the index of the item to create a pseudo bitmask key. The key is a single integer. What this means is that now we can pass around an integer ID for everything in the game, instead of the item itself.

Here is an example of my GameDatabase with the file loading trimmed out. I am also using C# because I absolutely abhor Java.

using System;
using System.Collections.Generic;
using VoidwalkerEngine.Framework.Collections;
using VoidwalkerEngine.Framework.DataTypes;
using VoidwalkerEngine.Framework.Entities;
using VoidwalkerEngine.Framework.Game.Items;
using VoidwalkerEngine.Framework.Rendering.OpenGL.Modeling;

namespace VoidwalkerEngine.Framework.Game.Managers
{

    public enum DatabaseLocation
    {
        Abilities,
        Apparel,
        Actors,
        Classes,
        Events,
        Items,
        LootTables,
        LootTablePools,
        Models,
        Sounds,
        StatusEffects,
        Weapons
    }

    public static class GameDatabase
    {

        public static List<Ability> Abilities;
        public static List<Actor> Actors;
        public static List<Birthsign> Classes;
        public static List<GameEvent> Events;
        public static List<GameItem> Items;
        public static List<Weapon> Weapons;
        public static List<Apparel> Apparel;
        public static List<LootTable> LootTables;
        public static List<LootTablePool> LootPools;
        public static List<VoidwalkerModel> Models;
        public static List<GameSound> Sounds;
        public static List<StatusEffect> StatusEffects;

        public static void Create()
        {
            Abilities = new List<Ability>();
            Actors = new List<Actor>();
            Classes = new List<Birthsign>();
            Events = new List<GameEvent>();
            Items = new List<GameItem>();
            Weapons = new List<Weapon>();
            Apparel = new List<Apparel>();
            LootTables = new List<LootTable>();
            LootPools = new List<LootTablePool>();
            Models = new List<VoidwalkerModel>();
            Sounds = new List<GameSound>();
            StatusEffects = new List<StatusEffect>();
        }

        public static void Initialize(int identifier)
        {
            Initialize(new DatabaseKey(identifier));
        }

        /// <summary>
        /// Initializes the Database location with a new Object of that type.
        /// The identifier for the object is automatically added.
        /// </summary>
        /// <param name="key"></param>
        public static void Initialize(DatabaseKey key)
        {
            int identifier = key.Identifier;
            int index = key.Index;
            switch (key.Location)
            {
                case DatabaseLocation.Abilities:
                    Abilities[index] = new Ability(identifier);
                    break;
                case DatabaseLocation.Apparel:
                    Apparel[index] = new Apparel(identifier);
                    break;
                case DatabaseLocation.Actors:
                    Actors[index] = new Actor(identifier);
                    break;
                case DatabaseLocation.Classes:
                    Classes[index] = new Birthsign(identifier);
                    break;
                case DatabaseLocation.Events:
                    Events[index] = new GameEvent(identifier);
                    break;
                case DatabaseLocation.Items:
                    Items[index] = new GameItem(identifier);
                    break;
                case DatabaseLocation.LootTables:
                    LootTables[index] = new LootTable(identifier);
                    break;
                case DatabaseLocation.LootTablePools:
                    LootPools[index] = new LootTablePool(identifier);
                    break;
                case DatabaseLocation.Models:
                    Models[index] = new VoidwalkerModel(identifier);
                    break;
                case DatabaseLocation.Sounds:
                    Sounds[index] = new GameSound(identifier);
                    break;
                case DatabaseLocation.StatusEffects:
                    StatusEffects[index] = new StatusEffect(identifier);
                    break;
                case DatabaseLocation.Weapons:
                    Weapons[index] = new Weapon(identifier);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }

        public static object Query(int identifier)
        {
            return Query(new DatabaseKey(identifier));
        }

        public static object Query(DatabaseKey key)
        {
            int index = key.Index;
            switch (key.Location)
            {
                case DatabaseLocation.Abilities:
                    return Abilities[index];
                case DatabaseLocation.Apparel:
                    return Apparel[index];
                case DatabaseLocation.Actors:
                    return Actors[index];
                case DatabaseLocation.Classes:
                    return Classes[index];
                case DatabaseLocation.Events:
                    return Events[index];
                case DatabaseLocation.Items:
                    return Items[index];
                case DatabaseLocation.LootTables:
                    return LootTables[index];
                case DatabaseLocation.LootTablePools:
                    return LootPools[index];
                case DatabaseLocation.Models:
                    return Models[index];
                case DatabaseLocation.Sounds:
                    return Sounds[index];
                case DatabaseLocation.StatusEffects:
                    return StatusEffects[index];
                case DatabaseLocation.Weapons:
                    return Weapons[index];
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }
}

In order to access an item in the database, you need to use this class to create a key for said item:

using System;
using VoidwalkerEngine.Framework.Game.Managers;

namespace VoidwalkerEngine.Framework.DataTypes
{
    public struct DatabaseKey : IEquatable<DatabaseKey>
    {
        #region Fields
        /// <summary>
        /// The Location within the Database
        /// </summary>
        public DatabaseLocation Location { get; }

        /// <summary>
        /// The Index of the Database List
        /// </summary>
        public int Index { get; }

        /// <summary>
        /// The Packed Identifier of this DatabaseKey
        /// </summary>
        public int Identifier
        {
            get
            {
                return Pack(Location, Index);
            }
        }
        #endregion

        #region Constants
        /// <summary>
        /// The Masking Multiplier. This is 10,000
        /// which means the maximum number of Items,
        /// Weapons,Apparel, etc are 9,999 for each
        /// Database List. If this number is increased
        /// it will also increase the maximum number of items.
        /// MaskMultiplier = 100,000 > 99,999 maximum items.
        /// </summary>
        public const int MaskMultiplier = 10000;
        public const int MinimumIndex = 0;
        public const int MaximumIndex = MaskMultiplier - 1;
        #endregion

        #region Constructors
        public DatabaseKey(string hexString) : this(Convert.ToInt32(hexString, 16)) { }
        public DatabaseKey(int identifier) : this(UnpackLocation(identifier), UnpackIndex(identifier)) { }
        public DatabaseKey(DatabaseKey other) : this(other.Location, other.Index) { }
        public DatabaseKey(DatabaseLocation location, int index)
        {
            this.Location = location;
            this.Index = index;
        }
        #endregion

        #region Functions
        /// <summary>
        /// Unpacks the Location from a packed HexCode.
        /// </summary>
        /// <param name="hexCode"></param>
        /// <returns></returns>
        public static DatabaseLocation UnpackLocation(int hexCode)
        {
            return (DatabaseLocation)(hexCode / MaskMultiplier);
        }

        /// <summary>
        /// Unpacks the Index within a packed HexCode.
        /// </summary>
        /// <param name="hexCode"></param>
        /// <returns></returns>
        public static int UnpackIndex(int hexCode)
        {
            return ((hexCode - ((hexCode / MaskMultiplier) * MaskMultiplier)) - 1);
        }

        /// <summary>
        /// Packs a Location and Index into an Identifier.
        /// </summary>
        /// <param name="location"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static int Pack(DatabaseLocation location, int index)
        {
            return ((((int)location * MaskMultiplier) + index) + 1);
        }
        #endregion

        #region Overrides
        public bool Equals(DatabaseKey other)
        {
            return Identifier == other.Identifier;
        }

        public override bool Equals(object obj)
        {
            return obj is DatabaseKey reference && Equals(reference);
        }

        public override int GetHashCode()
        {
            return Identifier;
        }

        public override string ToString()
        {
            return "0x" + Identifier.ToString("X");
        }
        #endregion
    }
}

The DatabaseKey is declared as an immutable struct. In order to create a key for an item you do something like:

DatabaseKey key = new DatabaseKey(DatabaseLocation.Items,24);

This results in an Integer identifier of: 50025 or in hex: 0xC369. What that means is that basic game items are located within the range of 50000-59999. So you take 50,000 + array index. This gives us a single integer in which to map items. Passing items around internally would then use an ItemStack implementation; here is mine:

using System;
using VoidwalkerEngine.Framework.Maths;

namespace VoidwalkerEngine.Framework.DataTypes
{
    [Serializable]
    public class ItemStack
    {

        /// <summary>
        /// The ID of the Associated Item.
        /// </summary>
        public int Identifier { get; set; }

        private int _quantity;

        /// <summary>
        /// The Quantity of this ItemStack.
        /// </summary>
        public int Quantity
        {
            get
            {
                return _quantity;
            }
            set
            {
                this._quantity = VoidwalkerMath.Clamp(value, MinQuantity, MaxQuantity);
            }
        }

        private int _maxQuantity = Int32.MaxValue;

        /// <summary>
        /// The Maximum Quantity of this Stack.
        /// </summary>
        public int MaxQuantity
        {
            get
            {
                return _maxQuantity;
            }
            set
            {
                this._maxQuantity = VoidwalkerMath.Clamp(value, MinQuantity, Int32.MaxValue);
                this.Quantity = this.Quantity;
            }
        }

        public const int MinQuantity = 0;

        public bool IsStackable
        {
            get
            {
                return this.MaxQuantity != 1;
            }
        }

        /// <summary>
        ///
        /// </summary>
        public bool IsEmpty
        {
            get
            {
                return this.Quantity == MinQuantity;
            }
        }

        /// <summary>
        ///
        /// </summary>
        public bool IsFull
        {
            get
            {
                return this.Quantity == this.MaxQuantity;
            }
        }

        public ItemStack()
        {

        }

        public ItemStack(int identifier, int quantity = 1, int maxQuantity = Int32.MaxValue)
        {
            this.Identifier = identifier;
            this.Quantity = quantity;
            this.MaxQuantity = maxQuantity;
        }

        /// <summary>
        /// Adds the specified quantity to this ItemStack. If
        /// the ItemStack is already full or close to being full,
        /// this ItemStack will overflow into a new ItemStack as the
        /// return value.
        /// </summary>
        /// <param name="quantity"></param>
        /// <returns></returns>
        public ItemStack Add(int quantity)
        {
            if (quantity <= MinQuantity)
            {
                return null;
            }
            int overflow = ComputeOverflow(quantity);
            if (overflow > MinQuantity)
            {
                this.Quantity += quantity;
                return new ItemStack(this.Identifier, overflow, this.MaxQuantity);
            }
            this.Quantity += quantity;
            return null;
        }

        /// <summary>
        /// Adds the specified quantity to this ItemStack. If
        /// the ItemStack is already full or close to being full,
        /// this ItemStack will overflow into a new ItemStack as the
        /// return value.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public ItemStack Add(ItemStack other)
        {
            ItemStack stack = Add(other.Quantity);
            other.Subtract(other.Quantity);
            return stack;
        }

        /// <summary>
        /// Subtracts the specified quantity from this ItemStack. If
        /// the ItemStack is already empty or close to being empty,
        /// this ItemStack will underflow into a new ItemStack as the
        /// return value.
        /// </summary>
        /// <param name="quantity"></param>
        /// <returns></returns>
        public ItemStack Subtract(int quantity)
        {
            if (quantity <= MinQuantity)
            {
                return null;
            }
            int underflow = ComputeUnderflow(quantity);
            if (underflow > MinQuantity)
            {
                this.Quantity -= (quantity - underflow);
            }
            this.Quantity -= quantity;
            return new ItemStack(this.Identifier, quantity, this.MaxQuantity);
        }

        /// <summary>
        /// Subtracts the specified quantity from this ItemStack. If
        /// the ItemStack is already empty or close to being empty,
        /// this ItemStack will underflow into a new ItemStack as the
        /// return value.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public ItemStack Subtract(ItemStack other)
        {
            ItemStack stack = Subtract(other.Quantity);
            other.Subtract(stack.Quantity);
            return stack;
        }

        /// <summary>
        /// Clears the Quantity of this ItemStack to 0. MaxValue, however, remains the same.
        /// </summary>
        public void Clear()
        {
            this._quantity = MinQuantity;
        }

        /// <summary>
        /// Makes the currect Quantity of this ItemStack equal to the MaxValue of this ItemStack.
        /// </summary>
        public void Fill()
        {
            this._quantity = MaxQuantity;
        }

        /// <summary>
        /// Splits this ItemStack into another, giving half to both stacks.
        /// If the split amount is an odd number, the result gets +1 so no
        /// loss of items happens due to rounding errors.
        /// </summary>
        /// <returns></returns>
        public ItemStack Split()
        {
            if (this.Quantity <= (MinQuantity + 1))
            {
                return null; // A split is impossible.
            }
            int splitResult = (this.Quantity / 2);
            if (this.Quantity % 2 == 0)
            {
                this.Quantity = splitResult;
                return new ItemStack(this.Identifier, splitResult, this.MaxQuantity);
            }
            this.Quantity = splitResult;
            return new ItemStack(this.Identifier, splitResult + 1, this.MaxQuantity);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="other"></param>
        public void Copy(ItemStack other)
        {
            this.Identifier = other.Identifier;
            this.Quantity = other.Quantity;
            this.MaxQuantity = other.MaxQuantity;
        }

        /// <summary>
        /// Creates a new ItemStack which is an exact copy of this ItemStack.
        /// </summary>
        /// <returns></returns>
        public ItemStack MakeCopy()
        {
            return new ItemStack(this.Identifier, this.Quantity, this.MaxQuantity);
        }

        /// <summary>
        /// Determines if this ItemStack is stackable with another ItemStack. This function tests
        /// for a match between the string Identifiers, and whether or not this ItemStack is Stackable.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool IsStackableWith(ItemStack other)
        {
            return this.Identifier == other.Identifier && this.IsStackable;
        }

        /// <summary>
        /// Calculates the amount of overflow that will take place
        /// if the desired ItemStack is added to this one.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int ComputeOverflow(ItemStack other)
        {
            return ComputeOverflow(other.Quantity);
        }

        /// <summary>
        /// Calculates the amount of overflow that will take place
        /// if the desired amount is added to this one.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public int ComputeOverflow(int amount)
        {
            if (amount <= MinQuantity)
            {
                return MinQuantity;
            }
            int total = ((this.Quantity + amount) - this.MaxQuantity);
            if (total < MinQuantity)
            {
                return MinQuantity;
            }
            return total;
        }

        /// <summary>
        /// Calculates the amount of underflow that will take place
        /// if the desired ItemStack is subtracted from this one.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public int ComputeUnderflow(ItemStack other)
        {
            return ComputeUnderflow(other.Quantity);
        }

        /// <summary>
        /// Calculates the amount of underflow that will take place
        /// if the desired amount is subtracted from this one.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public int ComputeUnderflow(int amount)
        {
            if (amount <= MinQuantity)
            {
                return MinQuantity;
            }
            int total = (this.Quantity - amount);
            if (total > MinQuantity)
            {
                return MinQuantity;
            }
            return Math.Abs(total);
        }

        /// <summary>
        /// Determines if this ItemStack has the specified quantity.
        /// If the quantity is less than or equal to 0, this function
        /// will always return false.
        /// </summary>
        /// <param name="quantity"></param>
        /// <returns></returns>
        public bool HasQuantity(int quantity)
        {
            if (quantity <= MinQuantity)
            {
                return false;
            }
            return this.Quantity >= quantity;
        }

        /// <summary>
        /// Determines if this ItemStack can still fit the specified amount
        /// without overflowing into a new ItemStack. If the quantity is less
        /// than or equal to 0, this function will always return false.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool CanHold(ItemStack other)
        {
            return CanHold(other.Quantity);
        }

        /// <summary>
        /// Determines if this ItemStack can still fit the specified amount
        /// without overflowing into a new ItemStack. If the quantity is less
        /// than or equal to 0, this function will always return false.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public bool CanHold(int amount)
        {
            if (amount <= MinQuantity)
            {
                return false;
            }
            return this.Quantity + amount <= MaxQuantity;
        }

        /// <summary>
        /// Determines if this ItemStack can subtract the specified amount
        /// without underflowing into a new ItemStack. If the quantity is less
        /// than or equal to 0, this function will always return false.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool CanSubtract(ItemStack other)
        {
            return CanSubtract(other.Quantity);
        }

        /// <summary>
        /// Determines if this ItemStack can subtract the specified amount
        /// without underflowing into a new ItemStack. If the quantity is less
        /// than or equal to 0, this function will always return false.
        /// </summary>
        /// <param name="amount"></param>
        /// <returns></returns>
        public bool CanSubtract(int amount)
        {
            if (amount <= MinQuantity)
            {
                return false;
            }
            return this.Quantity - amount >= MinQuantity;
        }

        public bool Equals(ItemStack other)
        {
            if (other != null)
            {
                return
                    this.Identifier == other.Identifier &&
                    this.Quantity == other.Quantity &&
                    this.MaxQuantity == other.MaxQuantity;
            }
            return false;
        }

        public override string ToString()
        {
            return $"{this.Identifier},{this.Quantity},{this.MaxQuantity}";
        }
    }
}

For more information on this ItemStack implementation, please see another answer I posted here: https://gamedev.stackexchange.com/questions/133000/how-do-inventories-work/133024

We do not pass around items. We pass around the integer ID's. This means we don't need to do any fancy polymorphism at all. When you need to get an item from the database, you just feed in the ID, use the location to cast it to the correct item(or other things that can achieve the cast on a dynamic level) and there you have it. This system also allows dynamic item generation. All you have to do is add another database List for Procedural Weapons, or Apparel. In the game when you augment an item, you're really just creating a new item, adding it to a list in the Database, removing the associated ItemStack from the players inventory, and then adding the new ItemStack with the new generated ID, which points to the created item in the database.

And finally, I believe a picture is worth a thousand words, so here is a screenshot of my engine using the Database system I have mentioned:

It should also be noted that this system scales very well with SQLite databases for actual storage and retrieval later down the road in your development. Essentially, you can rewrite the Database class that I have shown you to be a Query-Cache facade. So you first test to see if the item has been queried from the SQLite file already, and if it has, you just return the copy that you have already queried, else you query the item, cache it in the in-memory database, and then return it. This can greatly speed up your performance. The internal SQLite database is also very good at handling your custom integer indexes. All you would need to do for that is have a table in the SQLite file for each item type, then use the DatabaseKey struct to find out what type of item you're after, then use that to select the table from the SQLite file.

If you have any questions, I would be happy to answer them.


来源: stackexchange

问:
vim replaces lines when I move to a new line
I'm using Terminal.app on Mac 10.6.6 and want to upgrade vim. Should I install it in /usr/local?

I'm asking because my native vim install is messed up for some reason. Sometimes, when I open it and move up and down, the whole line changes to another line on the screen, like dancing chairs. But if I type :q it quits fine because nothing actually gets changed (cause I'm just moving the cursor around), but I can't see what I'm doing because when I move to a new line, that line gets replaced with another line about 6 lines below, but it's random.

$TERM = xterm-color

I installed Mercurial & ack via CPAN (for which I installed File:Next) yesterday, so maybe that did it. I have MacVim, but I want vim to work too cause I use it for Git, etc.

答:
Put the mvim script that came with MacVim in your $PATH and use it on the terminal with the -v option or a symbolic link named vim.

Also, use TERM=dtterm for Terminal.app.  Programs will behave better.

ContentLicense: CC BY-SA 2.5


问:
Puppeteer screenshot stop in random URL
I have a service nodejs working in Ubuntu, using puppeteer to take screenshots of pages, but in some pages the method page.screenshot({fullPage: true, type: 'jpeg'}) doesn't works in some random URLs and no errors are displayed in the log. The code is:

```<code>async takeScreenshot() {
        console.log('trying take Screenshot [...]');
        let image = await this.page.screenshot({fullPage: true, type: 'jpeg'});
        console.log('Completed!');
        return image;
    }
</code>```

An example of page that I had this problem is: https://nuevo.jumbo.cl/mayonesa-hellmanns-751-g-supreme-light/p

答:
It seems you are not waiting until the page is fully loaded before you take the screenshot. You need 'waitUntil':

```<code>    const page = await browser.newPage();
    await page.goto(inputImgUrl, {waitUntil: 'networkidle'});
</code>```

So the whole thing should look like something like this:

```<code>(async() => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(inputImgUrl, {waitUntil: 'networkidle'});
    await page.setViewport(viewPortData);
    await page.screenshot({path: outputFile, type: 'jpeg', quality: 50, clip: cropData});

    await browser.close();
})();
</code>```

ContentLicense: CC BY-SA 3.0

Title: Puppeteer screenshot stop in random URL

Body:
I have a service nodejs working in Ubuntu, using puppeteer to take screenshots of pages, but in some pages the method page.screenshot({fullPage: true, type: 'jpeg'}) doesn't works in some random URLs and no errors are displayed in the log. The code is:

async takeScreenshot() {
        console.log('trying take Screenshot [...]');
        let image = await this.page.screenshot({fullPage: true, type: 'jpeg'});
        console.log('Completed!');
        return image;
    }

An example of page that I had this problem is: https://nuevo.jumbo.cl/mayonesa-hellmanns-751-g-supreme-light/p

Body:
It seems you are not waiting until the page is fully loaded before you take the screenshot. You need 'waitUntil':

    const page = await browser.newPage();
    await page.goto(inputImgUrl, {waitUntil: 'networkidle'});

So the whole thing should look like something like this:

(async() => {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(inputImgUrl, {waitUntil: 'networkidle'});
    await page.setViewport(viewPortData);
    await page.screenshot({path: outputFile, type: 'jpeg', quality: 50, clip: cropData});

    await browser.close();
})();


问:
How to loop through an array of arrays using jQuery or JavaScript?
I have a json array like this

```<code>var data = key: [
    {
        arr1: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    },
    {
        arr2: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    },
    {
        arr3: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    }
]
</code>```

I wanted to loop through key which is 3 times, and inside the key loop I wanted loop again through each of the elements inside key.

First I tried $.each which works fine for key array. And inside the each function I tried to get the key values using Object.key(this) inside the loop which returned me the names

```<code>arr1, arr2, arr3
</code>```

But I'm not able to loop through the names I got.

```<code>$.each(data, function(i, e) {
    Object.keys(this).each(function(index, element) {
        console.log(element);
    })
})
</code>```

I don't know if this is the right way of doing it, when I tried doing it this was. I got an error telling .each is not a function.

Any help will be much appreciated.

答:
The simple way to do this would be to use three loops, but trying to make that work with this taking on a new meaning in each loop would be unnecessarily complicated.

I recommend using .forEach and giving a clear name to each loop variable:

var data =  [
    {
        arr1: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    },
    {
        arr2: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    },
    {
        arr3: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    }
]

data.forEach(function (outerObj) {
  Object.keys(outerObj).forEach(function (key) {
    outerObj[key].forEach(function (item) {
      console.log(item);
    });
  });
});
    ```

Of course, there may be a better solution if you would actually tell us what you wanted to accomplish with these loops.

Body:
I have a json array like this

var data = key: [
    {
        arr1: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    },
    {
        arr2: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    },
    {
        arr3: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    }
]

I wanted to loop through key which is 3 times, and inside the key loop I wanted loop again through each of the elements inside key.

First I tried $.each which works fine for key array. And inside the each function I tried to get the key values using Object.key(this) inside the loop which returned me the names

arr1, arr2, arr3

But I'm not able to loop through the names I got.

$.each(data, function(i, e) {
    Object.keys(this).each(function(index, element) {
        console.log(element);
    })
})

I don't know if this is the right way of doing it, when I tried doing it this was. I got an error telling .each is not a function.

Any help will be much appreciated.

Body:
The simple way to do this would be to use three loops, but trying to make that work with this taking on a new meaning in each loop would be unnecessarily complicated.

I recommend using .forEach and giving a clear name to each loop variable:

var data =  [
    {
        arr1: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    },
    {
        arr2: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    },
    {
        arr3: [
            {value: 1},
            {value: 2},
            {value: 3},
        ]
    }
]

data.forEach(function (outerObj) {
  Object.keys(outerObj).forEach(function (key) {
    outerObj[key].forEach(function (item) {
      console.log(item);
    });
  });
});

Of course, there may be a better solution if you would actually tell us what you wanted to accomplish with these loops.


问:
What is the difference between palindrome permutation and permutation?
I've seen coding questions to check whether a strings is a permutation of a palindrome, other times to check whether a string is a permutation of another string. Not sure I see the difference between the two. If a string is a permutation of a palindrome, both of them need to have the same length also the count of each character in both strings should be the same. The very same criteria can be said about a string after permutation. Are there any intrinsic differences between palindrome permutation and permutation from algorithm point of view?</p>

答:
These two questions typically differ based on how they’re framed. Usually, the string permutation question is asked as

Given a string w and a string x, check whether w is a permutation of x.

In that sense, you know what both strings are, and you just need to see whether the character counts match (or whether they have the same sorted order, etc.)

The palindrome permutation problem is typically asked as

Given a string w, determine whether there is a string x where x is a palindrome and w is a permutation of x.

So in this case, you’re just given a single string w and need to figure out whether somewhere out there there’s a palindrome that it’s a permutation of. This problem is different, since you don’t have an explicit target string to compare against and you need to have the creative insight of counting up the counts of each character to see whether there are exactly zero or one characters that appear an odd number of times.

The general problem of “is w a permutation of x?” ceases to be interesting if you reframe it as “is w a permutation of some string?” because the answer is an immediate “yes,” and the problem of “is w a permutation of some palindrome?” loses its charm if you reframe it as “is w a permutation of the palindrome x?” because it’s essentially the same as the general permutation problem.


问:
x-robots tag for query string parameter
I want to block a query string url's in .htaccess using x-robots tag. The url's are something like:

```<code>https://www.example.com/test?limit=60
https://www.example.com/test?limit=45
https://www.example.com/test?limit=all
</code>```

I need to block the ?limit=xxx

Ive tried something like this but it doesnt work:

```<code><IfModule mod_headers.c>
<Files "^limit=?$">
Header set X-Robots-Tag "noindex, nofollow"
</Files>
</IfModule>
</code>```

答:
Regular expressions don't work like that. Some pertinent differences:

? and * are quantifiers, not catch-all "match anything" tokens.

^ matches the beginning of the string.

This should work instead:

```<code><IfModule mod_headers.c>
<Files "\?(.*&)?limit=(\d+|all)(&.*)$">
Header set X-Robots-Tag "noindex, nofollow"
</Files>
</IfModule>
</code>```

Title: x-robots tag for query string parameter

Body:
I want to block a query string url's in .htaccess using x-robots tag. The url's are something like:

https://www.example.com/test?limit=60
https://www.example.com/test?limit=45
https://www.example.com/test?limit=all

I need to block the ?limit=xxx

Ive tried something like this but it doesnt work:

<IfModule mod_headers.c>
<Files "^limit=?$">
Header set X-Robots-Tag "noindex, nofollow"
</Files>
</IfModule>

Body:
Regular expressions don't work like that. Some pertinent differences:

? and * are quantifiers, not catch-all "match anything" tokens.

^ matches the beginning of the string.

This should work instead:

<IfModule mod_headers.c>
<Files "\?(.*&)?limit=(\d+|all)(&.*)$">
Header set X-Robots-Tag "noindex, nofollow"
</Files>
</IfModule>


问:
Page isn't working error, Node js freezes
I'm using Node for the first time and am having trouble when a certain response is triggered. In this case, I'm checking if the username and pw matches what I have in DynamoDB. It redirects to my page when the username and pw don't match my db, but when it does, all of my console.log output prints twice (which apparently has something to do with the favicon in Chrome) like "online" and "[pw] + database.js," but it also freezes my IDE and terminal. I then see the "The page isn't working, localhost didn't send any data" error in my browser. Ignore the privacy problems :) Thoughts?

database.js:

```<code>var myDB_lookup = function(username, password, route_callbck){
      console.log('Looking up: ' + username);
      users.get(username, function (err, data) {
        if (err) {
          route_callbck(null, "Lookup error: "+err);
        } else if (data == null) {
          route_callbck(null, null);
        } else {
          // JSON object that stores password & fullname
          var value = JSON.parse(data[0].value);
          var pw = value.password;
          if (pw.valueOf() == password.valueOf()){
              route_callbck({ password : pw }, null);
              console.log(pw + "database.js");
          }else{
              //console.log('wrong password');
              route_callbck(null, null);
          }
        }
      });
};
</code>```

routes.js:

```<code>var checkLogin = function(req,res){
    var user = req.body.username;
    var pw = req.body.password;
    console.log(user + pw + "routes");

    db.lookup(user, pw, function(data, err) {
          if (data!=null){
              console.log("online");
              //req.session.username = user;
              //req.session.password = pw;
          }else{
              res.render('main.ejs',{error:"Fields incorrect"});
          }
    });

};
</code>```

main.ejs:

```<code><form method="post" action="/checklogin">
    Enter username here: <br>
    <input type="text" name="username" placeholder = "Your username"> <br>
    Enter password here: <br>
    <input type="password" name="password" placeholder = "Your password">
    <input type="submit" value="Log In">
</form>
</code>```

The functions are all linked up in routes.js when I do module.exports = ...

答:
You probably forget to send the response, make sure

res.render() or res.json() or res.send() gets hit

you should put a try/catch around JSON.parse(), that's a best practice.

Looks like your culprit is here:

```<code>         if (data!=null){
              console.log("online");
              //req.session.username = user;
              //req.session.password = pw;

              // you need to send the response here too!  <<<<<
             res.render('main.ejs'); //// !!!
          }else{
              res.render('main.ejs',{error:"Fields incorrect"});
          }
</code>```

Body:
I'm using Node for the first time and am having trouble when a certain response is triggered. In this case, I'm checking if the username and pw matches what I have in DynamoDB. It redirects to my page when the username and pw don't match my db, but when it does, all of my console.log output prints twice (which apparently has something to do with the favicon in Chrome) like "online" and "[pw] + database.js," but it also freezes my IDE and terminal. I then see the "The page isn't working, localhost didn't send any data" error in my browser. Ignore the privacy problems :) Thoughts?

database.js:

var myDB_lookup = function(username, password, route_callbck){
      console.log('Looking up: ' + username);
      users.get(username, function (err, data) {
        if (err) {
          route_callbck(null, "Lookup error: "+err);
        } else if (data == null) {
          route_callbck(null, null);
        } else {
          // JSON object that stores password & fullname
          var value = JSON.parse(data[0].value);
          var pw = value.password;
          if (pw.valueOf() == password.valueOf()){
              route_callbck({ password : pw }, null);
              console.log(pw + "database.js");
          }else{
              //console.log('wrong password');
              route_callbck(null, null);
          }
        }
      });
};

routes.js:

var checkLogin = function(req,res){
    var user = req.body.username;
    var pw = req.body.password;
    console.log(user + pw + "routes");

    db.lookup(user, pw, function(data, err) {
          if (data!=null){
              console.log("online");
              //req.session.username = user;
              //req.session.password = pw;
          }else{
              res.render('main.ejs',{error:"Fields incorrect"});
          }
    });

};

main.ejs:

<form method="post" action="/checklogin">
    Enter username here:

    <input type="text" name="username" placeholder = "Your username">

    Enter password here:

    <input type="password" name="password" placeholder = "Your password">
    <input type="submit" value="Log In">
</form>

The functions are all linked up in routes.js when I do module.exports = ...

Body:
You probably forget to send the response, make sure

res.render() or res.json() or res.send() gets hit

you should put a try/catch around JSON.parse(), that's a best practice.

Looks like your culprit is here:

         if (data!=null){
              console.log("online");
              //req.session.username = user;
              //req.session.password = pw;

              // you need to send the response here too!  <<<<<
             res.render('main.ejs'); //// !!!
          }else{
              res.render('main.ejs',{error:"Fields incorrect"});
          }


问:
How to overwrite a point in memory in c#?
I want to do have the following functionality:

```<code>var item0 = new Item();
var item1 = item0;
item0 = null;

Console.WriteLine(item1 == null); // true
</code>```

So I'd be overwriting the memory that item0 and item1 point to.
I figured maybe I could do this with pointers..? However, when I tried declaring an item pointer:

```<code>Item* itemPointer;
</code>```

i got an error. Any ideas?

答:
```<code>var item0
{
   get{return item0;}
   set
   {
     item0 = value;
     item1 = item0;
   }
}
</code>```

Something like this will overwrite the value of item1 every time the value of item0 changes.

Body:
I want to do have the following functionality:

var item0 = new Item();
var item1 = item0;
item0 = null;

Console.WriteLine(item1 == null); // true

So I'd be overwriting the memory that item0 and item1 point to.
I figured maybe I could do this with pointers..? However, when I tried declaring an item pointer:

Item* itemPointer;

i got an error. Any ideas?

Body:
var item0
{
   get{return item0;}
   set
   {
     item0 = value;
     item1 = item0;
   }
}

Something like this will overwrite the value of item1 every time the value of item0 changes.


问:
Show and Hide Div onMouseOver
Hey guys, need just a little bit of help here, it's very close to what I'm after but not quite.

I want the text links I hover over to animate hidden text in a target div. So when I hover over link A, that text fades in; when I hover over link B, the previous text fades away and new text fades in.

Here is my javascript:

```<code><script type="text/javascript">
function ShowHide(){
    $("#textMessages").animate({"height": "toggle"}, { duration: 1000 });
    }
</script>
</code>```

Here are my links:

```<code><a onMouseOver="ShowHide(); return false;" href="#">Message A</a>

<a onMouseOver="ShowHide(); return false;" href="#">Message B</a>

<a onMouseOver="ShowHide(); return false;" href="#">Message C</a>
</code>```

And here is my target div with text snippets to fade in and fade out:

```<code><div id="textMessages">

<div id="defaultMessage">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>

<div id="MessageA">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>

<div id="MessageB">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>

<div id="MessageC">
Lorem ipsum dolor sit amet, consectetur adipiscing elit
</div>

</div>
</code>```

I assume I will need to set the #MessageA/B/C display:none

答:
Here's my bid:

```<code>$(function(){
    var slideOut = null;
    $('#textMessages').slideUp(1000);
    $('#textMessages,.textMessagesLink').hover(function(){
        $("#textMessages").slideDown(1000);
        if (slideOut != null) {
            clearTimeout(slideOut);
            slideOut = null
        }
    },function(){
        slideOut = setTimeout(HideHide,1000);
    });
    function HideHide(){
        $('#textMessages').slideUp(1000);
    }
});
</code>```

Took advantage of a timer in doing so. Also, made small change to your links (added a class for reference) and made it so as long as you hover over the div, the div will also stay visible (easily modified by taking the '#textMessages,' out of the .hover() selector.

Working example: http://www.jsfiddle.net/bradchristie/zgbfa/1/
Another example of taking "content divs" into consideration: http://www.jsfiddle.net/bradchristie/zgbfa/3/ (Can play around with defaultDiv if you'd like as well.

Title: Show and Hide Div onMouseOver

Body:
Hey guys, need just a little bit of help here, it's very close to what I'm after but not quite.

I want the text links I hover over to animate hidden text in a target div. So when I hover over link A, that text fades in; when I hover over link B, the previous text fades away and new text fades in.

Here is my javascript:

Here are my links:

Message A

Message B

Message C

And here is my target div with text snippets to fade in and fade out:

Lorem ipsum dolor sit amet, consectetur adipiscing elit

Lorem ipsum dolor sit amet, consectetur adipiscing elit

Lorem ipsum dolor sit amet, consectetur adipiscing elit

Lorem ipsum dolor sit amet, consectetur adipiscing elit

I assume I will need to set the #MessageA/B/C display:none

Body:
Here's my bid:

$(function(){
    var slideOut = null;
    $('#textMessages').slideUp(1000);
    $('#textMessages,.textMessagesLink').hover(function(){
        $("#textMessages").slideDown(1000);
        if (slideOut != null) {
            clearTimeout(slideOut);
            slideOut = null
        }
    },function(){
        slideOut = setTimeout(HideHide,1000);
    });
    function HideHide(){
        $('#textMessages').slideUp(1000);
    }
});

Took advantage of a timer in doing so. Also, made small change to your links (added a class for reference) and made it so as long as you hover over the div, the div will also stay visible (easily modified by taking the '#textMessages,' out of the .hover() selector.

Working example: http://www.jsfiddle.net/bradchristie/zgbfa/1/
Another example of taking "content divs" into consideration: http://www.jsfiddle.net/bradchristie/zgbfa/3/ (Can play around with defaultDiv if you'd like as well.


问:
Start activity from service takes too long
I have a Service that when one function gives to me true it will start a new Activity but it takes like 5 seconds...

I've read about this issue, and I've found on StackOverflow this example to "avoid" this bug..

```<code>Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
try {
   pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
   e.printStackTrace();
}
</code>```

but sadly it doesn't start the Activity faster, I don't need to be inmmediate (better if it's possible), but I don't want to wait +5 seconds to launch the new Activity, do you knwo any trick to avoid this?

I'm using PendingIntent because I've found that guy that said that it should solve this issue :
Starting an activity from a service after HOME button pressed without the 5 seconds delay

Note

If I press back button it launch it autommatically, 0 delay, but I'm looking pressing the home button.

答:
I tested with the PendingIntent approach and couldn't find anything wrong. That seems to be working fine. However, for reference, here is what I tried at my end:

```<code>public class MyService extends Service {
    public static final String SERVICE_COMMAND = "COMMAND";
    public static final String TAG = "MyService";
    public static final int SERVICE_START = 0x01;
    public static final int START_ACTIVITY = 0x02;

    private class ServiceHandler extends Handler {
        public ServiceHandler(HandlerThread thread) {
            super(thread.getLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case START_ACTIVITY:
                    Intent ActivityIntent = new Intent(getApplicationContext(), TestActivity.class);
                    ActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
                            0, ActivityIntent, 0);
                    try {
                        pendingIntent.send();
                    } catch (PendingIntent.CanceledException e) {
                        e.printStackTrace();
                    }
                    Log.e(TAG, "Service started activity -> " + System.currentTimeMillis());
                default:
                    break;
            }
            super.handleMessage(msg);
        }
    }

    private HandlerThread mThread;
    private ServiceHandler mHandler;

    public MyService() {
        mThread = new HandlerThread("ServiceThread");
        mThread.start();
        mHandler = new ServiceHandler(mThread);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int id = intent.getIntExtra(SERVICE_COMMAND, SERVICE_START);
        switch (id) {
            case START_ACTIVITY:
                Log.e(TAG, "onStartCommand Service -> " + System.currentTimeMillis());
                mHandler.sendEmptyMessage(START_ACTIVITY);
                break;
            default:
                break;
        }
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
</code>```

Activity Code:

```<code>public class MainActivity extends AppCompatActivity {
    private static final String TAG = "Main";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate main activity -> " + System.currentTimeMillis());
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        Intent intent = new Intent(this, MyService.class);
        startService(intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "onPause main activity -> " + System.currentTimeMillis());
        Intent intent = new Intent(this, MyService.class);
        intent.putExtra(MyService.SERVICE_COMMAND, MyService.START_ACTIVITY);
        startService(intent);
    }
}
</code>```

You can try the same code at your end. May be it can help.

Body:
I have a Service that when one function gives to me true it will start a new Activity but it takes like 5 seconds...

I've read about this issue, and I've found on StackOverflow this example to "avoid" this bug..

Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
try {
   pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
   e.printStackTrace();
}

but sadly it doesn't start the Activity faster, I don't need to be inmmediate (better if it's possible), but I don't want to wait +5 seconds to launch the new Activity, do you knwo any trick to avoid this?

I'm using PendingIntent because I've found that guy that said that it should solve this issue :
Starting an activity from a service after HOME button pressed without the 5 seconds delay

Note

If I press back button it launch it autommatically, 0 delay, but I'm looking pressing the home button.

Body:
I tested with the PendingIntent approach and couldn't find anything wrong. That seems to be working fine. However, for reference, here is what I tried at my end:

public class MyService extends Service {
    public static final String SERVICE_COMMAND = "COMMAND";
    public static final String TAG = "MyService";
    public static final int SERVICE_START = 0x01;
    public static final int START_ACTIVITY = 0x02;

    private class ServiceHandler extends Handler {
        public ServiceHandler(HandlerThread thread) {
            super(thread.getLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case START_ACTIVITY:
                    Intent ActivityIntent = new Intent(getApplicationContext(), TestActivity.class);
                    ActivityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
                            0, ActivityIntent, 0);
                    try {
                        pendingIntent.send();
                    } catch (PendingIntent.CanceledException e) {
                        e.printStackTrace();
                    }
                    Log.e(TAG, "Service started activity -> " + System.currentTimeMillis());
                default:
                    break;
            }
            super.handleMessage(msg);
        }
    }

    private HandlerThread mThread;
    private ServiceHandler mHandler;

    public MyService() {
        mThread = new HandlerThread("ServiceThread");
        mThread.start();
        mHandler = new ServiceHandler(mThread);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int id = intent.getIntExtra(SERVICE_COMMAND, SERVICE_START);
        switch (id) {
            case START_ACTIVITY:
                Log.e(TAG, "onStartCommand Service -> " + System.currentTimeMillis());
                mHandler.sendEmptyMessage(START_ACTIVITY);
                break;
            default:
                break;
        }
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

Activity Code:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "Main";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate main activity -> " + System.currentTimeMillis());
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
        Intent intent = new Intent(this, MyService.class);
        startService(intent);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.e(TAG, "onPause main activity -> " + System.currentTimeMillis());
        Intent intent = new Intent(this, MyService.class);
        intent.putExtra(MyService.SERVICE_COMMAND, MyService.START_ACTIVITY);
        startService(intent);
    }
}

You can try the same code at your end. May be it can help.


问:
Select specific column based on data supplied using Powershell
I have a csv file that may have unknown headers, one of the columns will contain email addresses for example.

Is there a way to select only the column that contains the email addresses and save it as a list to a variable?

One csv could have the header say email, another could say emailaddresses, another could say email addresses another file might not even have the word email in the header. As you can see, the headers are different. So I want to be able to detect the correct column first and use that data further in the script. Once the column is identified based on the data it contains, select that column only.

I've tried the where-object and select-string cmdlets. With both, the output is the entire array and not just the data in the column I am wanting.

```<code>$CSV = import-csv file.csv
$CSV | Where {$_ -like "*@domain.com"}
</code>```

This outputs the entire array as all rows will contain this data.

答:
If you're using Import-Csv, the result is a PSCustomObject.

```<code>$CsvObject = Import-Csv -Path 'C:\Temp\Example.csv'

$Header = ($CsvObject | Get-Member | Where-Object { $_.Name -like '*email*' }).Name

$CsvObject.$Header
</code>```

This filters for the header containing email, then selects that column from the object.

Edit for requirement:

```<code>$Str = @((Get-Content -Path 'C:\Temp\Example.csv') -like '*@domain.com*')
$Headers = @((Get-Content -Path 'C:\Temp\Example.csv' -TotalCount 1) -split ',')

$Str | ConvertFrom-Csv -Delimiter ',' -Header $Headers
</code>```

Body:
I have a csv file that may have unknown headers, one of the columns will contain email addresses for example.

Is there a way to select only the column that contains the email addresses and save it as a list to a variable?

One csv could have the header say email, another could say emailaddresses, another could say email addresses another file might not even have the word email in the header. As you can see, the headers are different. So I want to be able to detect the correct column first and use that data further in the script. Once the column is identified based on the data it contains, select that column only.

I've tried the where-object and select-string cmdlets. With both, the output is the entire array and not just the data in the column I am wanting.

$CSV = import-csv file.csv
$CSV | Where {$_ -like "*@domain.com"}

This outputs the entire array as all rows will contain this data.

Body:
If you're using Import-Csv, the result is a PSCustomObject.

$CsvObject = Import-Csv -Path 'C:\Temp\Example.csv'

$Header = ($CsvObject | Get-Member | Where-Object { $_.Name -like '*email*' }).Name

$CsvObject.$Header

This filters for the header containing email, then selects that column from the object.

Edit for requirement:

$Str = @((Get-Content -Path 'C:\Temp\Example.csv') -like '*@domain.com*')
$Headers = @((Get-Content -Path 'C:\Temp\Example.csv' -TotalCount 1) -split ',')

$Str | ConvertFrom-Csv -Delimiter ',' -Header $Headers


问:
With ifstream while loop, how to show an input error and resume at the next line?
If my input file started with a letter it will stop the while loop because it cant rewrite int1, I know that but how would I be able to detect this and show an error message saying that workinfile>>int1 did not work and afterwards continue the loop?

```<code>cin>>filename;
ifstream workingfile(filename);

while (workingfile>>int1>>int2>>string1>>string2) {
    cout<<int1<<int2<<string1<<string2<<endl;
    linenumread++;
}
</code>```

I tried doing but it doesn't work, any help would be appreciated

```<code> while (workingfile>>int1>>int2>>string1>>string2) {
    if(!(workingfile>>int1))
    {
       cout<<"Error first value is not an integer"<<endl;
       continue;
    }
    cout<<int1<<int2<<string1<<string2<<endl;
    linenumread++;
}
</code>```

Also would it be possible to detect if it stops reading the strings as well?

The input file would look like this

```<code>10 10 ab bc
11 11 cd ef
a
12 12 gh hi
</code>```

I want to to detect when it hits an invalid input, show an error message, and continue with the next line in the file.

答:
For this kind of input, it's usually better to read a complete line, and then extract the values from that line.  If the line can't be parsed, you can report a failure for that line, and just continue from the start of the next line.

That would look something like this:

```<code>std::string line;
while (std::getline(workingfile, line)) // Read a whole line per cycle
{
    std::istringstream workingline(line); // Create a stream from the line
    // Parse all variables separately from the line's stream
    if(!(workingline>>int1))
    {
       cout<<"Error first value is not an integer"<<endl;
       continue;
    }
    if(!(workingline>>int2)
    {
       cout<<"Error second value is not an integer"<<endl;
       continue;
    }
    // ^^^^ a.s.o. ...
    cout<<int1<<int2<<string1<<string2<<endl;
    linenumread++;
}
</code>```

Body:
If my input file started with a letter it will stop the while loop because it cant rewrite int1, I know that but how would I be able to detect this and show an error message saying that workinfile>>int1 did not work and afterwards continue the loop?

cin>>filename;
ifstream workingfile(filename);

while (workingfile>>int1>>int2>>string1>>string2) {
    cout<<int1<<int2<<string1<<string2<<endl;
    linenumread++;
}

I tried doing but it doesn't work, any help would be appreciated

 while (workingfile>>int1>>int2>>string1>>string2) {
    if(!(workingfile>>int1))
    {
       cout<<"Error first value is not an integer"<<endl;
       continue;
    }
    cout<<int1<<int2<<string1<<string2<<endl;
    linenumread++;
}

Also would it be possible to detect if it stops reading the strings as well?

The input file would look like this

10 10 ab bc
11 11 cd ef
a
12 12 gh hi

I want to to detect when it hits an invalid input, show an error message, and continue with the next line in the file.

Body:
For this kind of input, it's usually better to read a complete line, and then extract the values from that line.  If the line can't be parsed, you can report a failure for that line, and just continue from the start of the next line.

That would look something like this:

std::string line;
while (std::getline(workingfile, line)) // Read a whole line per cycle
{
    std::istringstream workingline(line); // Create a stream from the line
    // Parse all variables separately from the line's stream
    if(!(workingline>>int1))
    {
       cout<<"Error first value is not an integer"<<endl;
       continue;
    }
    if(!(workingline>>int2)
    {
       cout<<"Error second value is not an integer"<<endl;
       continue;
    }
    // ^^^^ a.s.o. ...
    cout<<int1<<int2<<string1<<string2<<endl;
    linenumread++;
}


问:
java.lang.NoClassDefFoundError (libgdx)
Been trying to work with the Libgdx framework and have been experiencing some frustrating issues.. I'm following a tutorial and I'm unable to run my project. What am I doing wrong?

```<code>package com.mygdx.game.android;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class AndroidLauncher implements ApplicationListener {

    SpriteBatch batch;
    Texture mario;

    @Override
    public void create() {
        batch = new SpriteBatch();

        mario = new Texture(Gdx.files.internal("mario.png"));
    }

    @Override
    public void resize(int width, int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1,1,1,1);

        batch.begin();
        batch.draw(mario, 50, 50);
        batch.end();

    }

    @Override
    public void pause() {
        // TODO Auto-generated method stub

    }

    @Override
    public void resume() {
        // TODO Auto-generated method stub

    }

    @Override
    public void dispose() {
        // TODO Auto-generated method stub

    }

}
</code>```

Here's what the console displays when I run the project:

```<code>Exception in thread "main" java.lang.NoClassDefFoundError: com/badlogic/gdx/jnigen/NativeCodeGenerator
    at com.badlogic.gdx.utils.GdxBuild.main(GdxBuild.java:34)
Caused by: java.lang.ClassNotFoundException: com.badlogic.gdx.jnigen.NativeCodeGenerator
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 1 more
</code>```

答:
Project structure -> modules -> choose required module (desktop, android, etc) -> Dependencies -> Add Library.

Don't forget change Scope from "Provided" to "Compile".

Title: java.lang.NoClassDefFoundError (libgdx)

Body:
Been trying to work with the Libgdx framework and have been experiencing some frustrating issues.. I'm following a tutorial and I'm unable to run my project. What am I doing wrong?

package com.mygdx.game.android;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class AndroidLauncher implements ApplicationListener {

    SpriteBatch batch;
    Texture mario;

    @Override
    public void create() {
        batch = new SpriteBatch();

        mario = new Texture(Gdx.files.internal("mario.png"));
    }

    @Override
    public void resize(int width, int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1,1,1,1);

        batch.begin();
        batch.draw(mario, 50, 50);
        batch.end();

    }

    @Override
    public void pause() {
        // TODO Auto-generated method stub

    }

    @Override
    public void resume() {
        // TODO Auto-generated method stub

    }

    @Override
    public void dispose() {
        // TODO Auto-generated method stub

    }

}

Here's what the console displays when I run the project:

Exception in thread "main" java.lang.NoClassDefFoundError: com/badlogic/gdx/jnigen/NativeCodeGenerator
    at com.badlogic.gdx.utils.GdxBuild.main(GdxBuild.java:34)
Caused by: java.lang.ClassNotFoundException: com.badlogic.gdx.jnigen.NativeCodeGenerator
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 1 more


问:
Use Bundle-NativeCode on Linux does not work
I create a plugin which includes the following folder structure:

src

native/so/libsystemcommand.so

META-INF/MANIFEST.MF

The manifest include the command

```<code>Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Commands Plug-in
Bundle-SymbolicName: de.system.commands;singleton:=true
Bundle-Version: 1.0.0
Bundle-Activator: de.system.commands.CommandsPlugin
Bundle-Localization: plugin
Bundle-NativeCode: native/so/libsystemcommand.so; osname = Linux; processor = x86
Require-Bundle: org.eclipse.core.runtime,
 org.apache.commons.logging
Eclipse-AutoStart: true
Export-Package: de.system.commands,
 de.system.commands.jni,
 de.system.commands.utils
Bundle-ClassPath: .
</code>```

The build.properties looks like

```<code>source.. = src/
output.. = bin/
bin.includes = META-INF/,\
               .,\
               native/
</code>```

In the start method of my Activator class I call

```<code>System.loadLibrary("systemcommand");
</code>```

At runtime the library is not found and a UnsatisfiedLinkError is thrown.

```<code>java.lang.UnsatisfiedLinkError: no libsystemcommand in java.library.path
</code>```

Do I have to set more attributes in the plugin? Do I have to unzip some informations on the target platform?

EDIT:

```<code>java.library.path=/opt/jdk/j2re1.4.2_16/lib/i386/client:/opt/jdk/j2re1.4.2_16/lib/i386:/opt/jdk/j2re1.4.2_16/../lib/i386::/opt/dsa/lib:/opt/dsa/lib
</code>```

答:
I wonder if the library needs to be specified without the lib prefix?  E.g.,

```<code>System.loadLibrary("systemcommand");
</code>```

Since that is how the library would be passed on a gcc link line.

OwnerDisplayName: Markus Lausberg

Body:
I create a plugin which includes the following folder structure:

src

native/so/libsystemcommand.so

META-INF/MANIFEST.MF

The manifest include the command

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Commands Plug-in
Bundle-SymbolicName: de.system.commands;singleton:=true
Bundle-Version: 1.0.0
Bundle-Activator: de.system.commands.CommandsPlugin
Bundle-Localization: plugin
Bundle-NativeCode: native/so/libsystemcommand.so; osname = Linux; processor = x86
Require-Bundle: org.eclipse.core.runtime,
 org.apache.commons.logging
Eclipse-AutoStart: true
Export-Package: de.system.commands,
 de.system.commands.jni,
 de.system.commands.utils
Bundle-ClassPath: .

The build.properties looks like

source.. = src/
output.. = bin/
bin.includes = META-INF/,\
               .,\
               native/

In the start method of my Activator class I call

System.loadLibrary("systemcommand");

At runtime the library is not found and a UnsatisfiedLinkError is thrown.

java.lang.UnsatisfiedLinkError: no libsystemcommand in java.library.path

Do I have to set more attributes in the plugin? Do I have to unzip some informations on the target platform?

EDIT:

java.library.path=/opt/jdk/j2re1.4.2_16/lib/i386/client:/opt/jdk/j2re1.4.2_16/lib/i386:/opt/jdk/j2re1.4.2_16/../lib/i386::/opt/dsa/lib:/opt/dsa/lib

LastEditorDisplayName: Markus Lausberg

Body:
I wonder if the library needs to be specified without the lib prefix?  E.g.,

System.loadLibrary("systemcommand");

Since that is how the library would be passed on a gcc link line.

OwnerDisplayName: Andrew Eidsness