示例#1
0
 public void Register(string name)
 {
     if (canvas == null)
     {
         Debug.LogError("No canvas loaded, cannot filter!");
         return;
     }
     if (search == null)
     {
         List <Node> nodes = canvas.nodes;
         foreach (Node node in nodes)
         {
             IngredientNode iNode = node as IngredientNode;
             if (iNode == null)
             {
                 continue;
             }
             if (iNode.ingredientName != name)
             {
                 continue;
             }
             List <Node> candidates = CollectOutputNodes(iNode);
             search = new SearchState(candidates, name);
             break;
         }
     }
     else
     {
         search.Filter(name);
     }
 }
示例#2
0
        public void Filter(string name)
        {
            elements.Add(name);
            for (int index = 0; index < nodes.Count; index++)   // go through all nodes
            {
                Node node          = nodes[index];
                bool hasIngredient = false;

                foreach (NodeInput ipt in node.Inputs)               // look at all parents and if you've found the element
                {
                    Node           parent     = ipt.connection.body; // then signalize it - so it won't be deleted.
                    IngredientNode ingredient = GetIngredientNode(parent);
                    if (ingredient.ingredientName == name)
                    {
                        hasIngredient = true;
                        break;
                    }
                }

                if (!hasIngredient)
                {
                    nodes.Remove(node);
                }
            }
        }
示例#3
0
        List <IngredientNode> GetIngredients(HtmlNode documentNode)
        {
            var nodes       = documentNode.SelectNodes(ingredientPath);
            var ingredients = new List <IngredientNode>();

            foreach (var node in nodes)
            {
                var ingredient = new IngredientNode();
                ingredient.fullText = node.InnerText;
                ingredients.Add(ingredient);
            }
            return(ingredients);
        }
示例#4
0
            public void AddConnection(IngredientNode node)
            {
                if (connections == null)
                {
                   connections = new ConnectorVertex();
                }
                else
                {
                   if (connections.HasConnection(node))
                  return;
                }

                connections.AddConnection(node);
            }
示例#5
0
 void OnGUI()
 {
     if (GUI.Button(new Rect(5, 85, 60, 20), "TEST"))
     {
         CraftingInterface c = GetComponent <CraftingInterface>();
         Debug.Log(c);
         c.Register("Penis Herb");
         c.Register("V****a Herb");
         Node           node  = c.Retrieve();
         IngredientNode iNode = node as IngredientNode;
         if (iNode != null)
         {
             Debug.Log(iNode.ingredientName);
         }
     }
 }
示例#6
0
            public void AddConnection(IngredientNode node)
            {
                if (connections == null)
                {
                    connections = new ConnectorVertex();
                }
                else
                {
                    if (connections.HasConnection(node))
                    {
                        return;
                    }
                }

                connections.AddConnection(node);
            }
示例#7
0
            public void AddConnection(IngredientNode node)
            {
                if (this.Connections == null)
                {
                    this.Connections = new ConnectorVertex();
                }
                else
                {
                    if (this.Connections.HasConnection(node))
                    {
                        return;
                    }
                }

                this.Connections.AddConnection(node);
            }
示例#8
0
 // Use this for initialization
 void OnGUI()
 {
     if (GUI.Button(new Rect(5, 85, 60, 20), "TEST"))
     {
         CraftingInterface c = GetComponent <CraftingInterface>();
         Debug.Log(c);
         c.Register("Green Herb");
         c.Register("Blue Herb");
         Node           node   = c.Retrieve();
         IngredientNode recipe = node as IngredientNode;
         if (recipe != null)
         {
             Debug.Log(recipe.ingredientName);
         }
     }
 }
示例#9
0
    private List <Node> CollectOutputNodes(IngredientNode node)
    {
        List <Node>       result  = new List <Node>();
        List <NodeOutput> outputs = node.Outputs;

        foreach (NodeOutput opt in outputs)
        {
            foreach (NodeInput ipt in opt.connections)
            {
                Node candidate = ipt.body;
                result.Add(candidate);
            }
        }

        return(result);
    }
示例#10
0
    void Start()
    {
        canvas = NodeEditorSaveManager.LoadSceneNodeCanvas("CraftingCanvas", false);
        Debug.Log(canvas);
        IngredientNode iNode = Instantiate(canvas.nodes.Find(x => ((IngredientNode)x).ingredientName == "Green Herb")) as IngredientNode;
        BaseItem       item_ = new BaseItem(iNode);

        _inventory.Add(item_);
        iNode = Instantiate(canvas.nodes.Find(x => ((IngredientNode)x).ingredientName == "Blue Herb")) as IngredientNode;
        item_ = new BaseItem(iNode);
        _inventory.Add(item_);
        iNode = Instantiate(canvas.nodes.Find(x => ((IngredientNode)x).ingredientName == "Green Herb")) as IngredientNode;
        item_ = new BaseItem(iNode);
        _inventory.Add(item_);
        iNode = Instantiate(canvas.nodes.Find(x => ((IngredientNode)x).ingredientName == "Blue Herb")) as IngredientNode;
        item_ = new BaseItem(iNode);
        _inventory.Add(item_);
    }
示例#11
0
    public void Craft()
    {
        Node node = craftingInterface.Retrieve();

        recipe = node as IngredientNode;
        if (recipe != null)
        {
            myButton.interactable = false;
            removeItemsFromInventory();
            BaseItem product = new BaseItem((Instantiate(canvas.nodes.Find(x => ((IngredientNode)x).ingredientName == recipe.ingredientName)) as IngredientNode));
            generateItemAffix(product);
            InventoryWindow.playerInventory.Add(product);
            craftingInterface.ResetHistory();
            InventoryWindow.itemCounter.Clear();
        }
        else
        {
            myButton.interactable = false;
            removeItemsFromInventory();
            craftingInterface.ResetHistory();
            InventoryWindow.itemCounter.Clear();
            InventoryWindow.playerInventory.Add(new BaseItem());
        }
    }
    public void LoadScenery()
    {
        try
        {
            GameObject hider = new GameObject();
            char       dsc   = System.IO.Path.DirectorySeparatorChar;

            using (WWW www = new WWW("file://" + Path + dsc + "assetbundle" + dsc + "mod"))
            {
                if (www.error != null)
                {
                    throw new Exception("Loading had an error:" + www.error);
                }

                AssetBundle bundle = www.assetBundle;
                try
                {
                    XmlDocument doc   = new XmlDocument();
                    string[]    files = System.IO.Directory.GetFiles(Path, "*.xml");
                    doc.Load(files[0]);
                    XmlElement  xelRoot  = doc.DocumentElement;
                    XmlNodeList ModNodes = xelRoot.SelectNodes("/Mod");

                    foreach (XmlNode Mod in ModNodes)
                    {
                        modName        = Mod["ModName"].InnerText;
                        modDiscription = Mod["ModDiscription"].InnerText;
                    }
                    XmlNodeList ObjectNodes = xelRoot.SelectNodes("/Mod/Objects/Object");

                    foreach (XmlNode ParkOBJ in ObjectNodes)
                    {
                        try
                        {
                            ModdedObject MO    = null;
                            GameObject   asset = Instantiate(bundle.LoadAsset(ParkOBJ["OBJName"].InnerText)) as GameObject;
                            asset.name = Identifier + "@" + ParkOBJ["OBJName"].InnerText;
                            switch (ParkOBJ["Type"].InnerText)
                            {
                            case "deco":
                                DecoMod DM = new DecoMod();
                                DM.HeightDelta     = float.Parse(ParkOBJ["heightDelta"].InnerText);
                                DM.GridSubdivision = 1f;
                                DM.SnapCenter      = Convert.ToBoolean(ParkOBJ["snapCenter"].InnerText);
                                DM.category        = ParkOBJ["category"].InnerText;
                                DM.BuildOnGrid     = Convert.ToBoolean(ParkOBJ["grid"].InnerText);
                                DM.gridSubdivision = float.Parse(ParkOBJ["gridSubdivision"].InnerText);
                                MO = DM;
                                break;

                            case "trashbin":
                                MO = new TrashBinMod();
                                break;

                            case "seating":
                                SeatingMod SM = new SeatingMod();
                                SM.hasBackRest = false;
                                MO             = SM;
                                break;

                            case "seatingAuto":
                                SeatingAutoMod SMA = new SeatingAutoMod();
                                SMA.hasBackRest = false;
                                SMA.seatCount   = 2;
                                MO = SMA;
                                break;

                            case "lamp":
                                MO = new LampMod();
                                break;

                            case "fence":
                                FenceMod FM = new FenceMod();
                                FM.FenceFlat = null;
                                FM.FencePost = null;
                                MO           = FM;
                                break;

                            case "FlatRide":
                                FlatRideMod FR = new FlatRideMod();
                                FR.XSize                = (int)float.Parse(ParkOBJ["X"].InnerText);
                                FR.ZSize                = (int)float.Parse(ParkOBJ["Z"].InnerText);
                                FR.Excitement           = float.Parse(ParkOBJ["Excitement"].InnerText);
                                FR.Intensity            = float.Parse(ParkOBJ["Intensity"].InnerText);
                                FR.Nausea               = float.Parse(ParkOBJ["Nausea"].InnerText);
                                FR.closedAngleRetraints = getVector3(ParkOBJ["RestraintAngle"].InnerText);
                                RideAnimationMod RA = new RideAnimationMod();
                                RA.motors    = FlatRideLoader.LoadMotors(ParkOBJ, asset);
                                RA.phases    = FlatRideLoader.LoadPhases(ParkOBJ, asset);
                                FR.Animation = RA;
                                XmlNodeList WaypointsNodes = ParkOBJ.SelectNodes("Waypoints/Waypoint");
                                foreach (XmlNode xndNode in WaypointsNodes)
                                {
                                    Waypoint w = new Waypoint();
                                    w.isOuter          = Convert.ToBoolean(xndNode["isOuter"].InnerText);
                                    w.isRabbitHoleGoal = Convert.ToBoolean(xndNode["isRabbitHoleGoal"].InnerText);
                                    if (xndNode["connectedTo"].InnerText != "")
                                    {
                                        w.connectedTo = xndNode["connectedTo"].InnerText.Split(',').ToList().ConvertAll(s => Int32.Parse(s));
                                    }
                                    w.localPosition = getVector3(xndNode["localPosition"].InnerText);
                                    FR.waypoints.Add(w);
                                }
                                MO = FR;
                                break;

                            case "Shop":
                                ShopMod S = new ShopMod();

                                asset.SetActive(false);
                                XmlNodeList ProductNodes = ParkOBJ.SelectNodes("Shop/Product");
                                foreach (XmlNode ProductNode in ProductNodes)
                                {
                                    ProductMod PM = new ProductMod();
                                    switch (ProductNode["Type"].InnerText)
                                    {
                                    case "consumable":
                                        consumable C = new consumable();
                                        C.ConsumeAnimation = (consumable.consumeanimation)Enum.Parse(typeof(consumable.consumeanimation), ProductNode["ConsumeAnimation"].InnerText);
                                        C.Temprature       = (consumable.temprature)Enum.Parse(typeof(consumable.temprature), ProductNode["Temprature"].InnerText);
                                        C.portions         = Int32.Parse(ProductNode["Portions"].InnerText);
                                        PM = C;
                                        break;

                                    case "wearable":
                                        wearable W = new wearable();
                                        W.BodyLocation = (wearable.bodylocation)Enum.Parse(typeof(wearable.bodylocation), ProductNode["BodyLocation"].InnerText);
                                        PM             = W;
                                        break;

                                    case "ongoing":
                                        ongoing O = new ongoing();
                                        O.duration = Int32.Parse(ProductNode["Duration"].InnerText);
                                        PM         = O;
                                        break;

                                    default:
                                        break;
                                    }
                                    PM.Name = ProductNode["Name"].InnerText;
                                    PM.GO   = Instantiate(bundle.LoadAsset(ProductNode["Model"].InnerText)) as GameObject;
                                    PM.GO.SetActive(false);
                                    PM.Hand  = (ProductMod.hand)Enum.Parse(typeof(ProductMod.hand), ProductNode["Hand"].InnerText);
                                    PM.price = float.Parse(ProductNode["Price"].InnerText);
                                    XmlNodeList IngredientNodes = ProductNode.SelectNodes("Ingredients/Ingredient");
                                    foreach (XmlNode IngredientNode in IngredientNodes)
                                    {
                                        ingredient I = new ingredient();
                                        I.Name      = IngredientNode["Name"].InnerText;
                                        I.price     = float.Parse(IngredientNode["Price"].InnerText);
                                        I.amount    = float.Parse(IngredientNode["Amount"].InnerText);
                                        I.tweakable = Boolean.Parse(IngredientNode["tweakable"].InnerText);
                                        XmlNodeList EffectNodes = IngredientNode.SelectNodes("Effects/effect");
                                        foreach (XmlNode EffectNode in EffectNodes)
                                        {
                                            effect E = new effect();
                                            E.Type   = (effect.Types)Enum.Parse(typeof(effect.Types), EffectNode["Type"].InnerText);
                                            E.amount = float.Parse(EffectNode["Amount"].InnerText);
                                            I.effects.Add(E);
                                        }
                                        PM.ingredients.Add(I);
                                    }
                                    S.products.Add(PM);
                                }
                                MO = S;
                                break;

                            case "PathStyle":
                                Registar.RegisterPath(asset.GetComponent <Renderer>().material.mainTexture, ParkOBJ["inGameName"].InnerText, (Registar.PathType)Enum.Parse(typeof(Registar.PathType), ParkOBJ["PathStyle"].InnerText));
                                break;

                            case "CoasterCar":
                                Debug.Log("Test CoasterCar");
                                CoasterCarMod CC = new CoasterCarMod();
                                CC.CoasterName = ParkOBJ["CoasterName"].InnerText;
                                CC.Name        = ParkOBJ["inGameName"].InnerText;

                                try
                                {
                                    CC.closedAngleRetraints = getVector3(ParkOBJ["RestraintAngle"].InnerText);
                                    CC.FrontCarGO           = Instantiate(bundle.LoadAsset(ParkOBJ["FrontCarGO"].InnerText)) as GameObject;
                                }
                                catch
                                { }
                                MO        = CC;
                                MO.Name   = ParkOBJ["inGameName"].InnerText;
                                MO.Object = asset;

                                break;

                            default:
                                break;
                            }
                            if (MO != null)
                            {
                                MO.Name   = ParkOBJ["inGameName"].InnerText;
                                MO.Object = asset;
                                MO.Price  = float.Parse(ParkOBJ["price"].InnerText);
                                MO.Shader = ParkOBJ["shader"].InnerText;
                                if (ParkOBJ["BoudingBoxes"] != null)
                                {
                                    XmlNodeList BoudingBoxNodes = ParkOBJ.SelectNodes("BoudingBoxes/BoudingBox");
                                    foreach (XmlNode Box in BoudingBoxNodes)
                                    {
                                        BoundingBox BB = MO.Object.AddComponent <BoundingBox>();
                                        BB.isStatic   = false;
                                        BB.bounds.min = getVector3(Box["min"].InnerText);
                                        BB.bounds.max = getVector3(Box["max"].InnerText);
                                        BB.layers     = BoundingVolume.Layers.Buildvolume;
                                        BB.isStatic   = true;
                                    }
                                }
                                MO.Recolorable = Convert.ToBoolean(ParkOBJ["recolorable"].InnerText);
                                if (MO.Recolorable)
                                {
                                    List <Color> colors = new List <Color>();
                                    if (HexToColor(ParkOBJ["Color1"].InnerText) != new Color(0.95f, 0, 0))
                                    {
                                        colors.Add(HexToColor(ParkOBJ["Color1"].InnerText));
                                    }
                                    if (HexToColor(ParkOBJ["Color2"].InnerText) != new Color(0.32f, 1, 0))
                                    {
                                        colors.Add(HexToColor(ParkOBJ["Color2"].InnerText));
                                    }
                                    Debug.Log("Color 3" + HexToColor(ParkOBJ["Color3"].InnerText));
                                    if (ParkOBJ["Color3"].InnerText != "1C0FFF")
                                    {
                                        colors.Add(HexToColor(ParkOBJ["Color3"].InnerText));
                                    }
                                    if (HexToColor(ParkOBJ["Color4"].InnerText) != new Color(1, 0, 1))
                                    {
                                        colors.Add(HexToColor(ParkOBJ["Color4"].InnerText));
                                    }

                                    MO.Colors = colors.ToArray();
                                }
                                Registar.Register(MO).GetComponent <BuildableObject>();
                            }
                        }
                        catch (Exception e)
                        {
                            LogException(e);
                        }
                    }
                }
                catch (Exception e)
                {
                    LogException(e);
                }
                bundle.Unload(false);
                Debug.Log("Bundle Unloaded");
            }
        }
        catch (Exception e)
        {
            LogException(e);
        }
    }
示例#13
0
            public void Index(IKPCContext context)
            {
                var timer = new Stopwatch();
                timer.Start();

                ratingGraph = new RatingGraph();
                var loader = context.ModelerLoader;

                foreach (var dataItem in loader.LoadRatingGraph())
                {
                   var r = dataItem.Rating;
                   var uid = dataItem.UserId;
                   var rid = dataItem.RecipeId;

                   if (r < 4) //Rating too low to worry about
                   {
                  continue; //TODO: Might not be needed, DB should only query for 4 or 5 star ratings
                   }

                   ratingGraph.AddRating(r, uid, rid);
                }

                ModelingSession.Log.InfoFormat("Building Rating Graph took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
                timer.Start();

                //Create empty recipe nodes without links
                snapshot.recipeMap = (from o in loader.LoadRecipeGraph()
                   select new RecipeNode()
                   {
                  RecipeId = o.Id,
                  Rating = o.Rating,
                  Tags = o.Tags,
                  Hidden = o.Hidden,
                  Ingredients = new List<IngredientUsage>()
                   }).ToDictionary(k => k.RecipeId);

                ModelingSession.Log.InfoFormat("Building empty RecipeNodes took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
                timer.Start();

                //Build tag index
                foreach (var r in snapshot.recipeMap.Values)
                {
                   if (r.Hidden)
                  continue; //_recipeList does not include Hidden recipes so they don't get picked at random

                   foreach (var tag in r.Tags)
                   {
                  var nodes = snapshot.recipeList[tag.Value] as List<RecipeNode>;
                  if (nodes == null)
                     snapshot.recipeList[tag.Value] = nodes = new List<RecipeNode>();

                  nodes.Add(r);
                   }
                }

                for (var i = 0; i < snapshot.recipeList.Length; i++)
                {
                   var list = snapshot.recipeList[i] as List<RecipeNode>;
                   if (list != null)
                   {
                  snapshot.recipeList[i] = list.ToArray();
                   }
                   else //No recipes in DB use this tag
                   {
                  snapshot.recipeList[i] = new RecipeNode[0];
                   }
                }

                ModelingSession.Log.InfoFormat("Indexing recipes by tag took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
                timer.Start();

                //Loop through ingredient usages and fill in vertices on graph
                //For each item: Create IngredientUsage and add to recipe, create IngredientNode (if necessary) and add recipe to IngredientNode
                foreach (var o in loader.LoadIngredientGraph())
                {
                   var rid = o.RecipeId;
                   var ingid = o.IngredientId;
                   var qty = o.Qty;
                   var unit = o.Unit;
                   var convType = Unit.GetConvType(unit);

                   List<RecipeNode>[] nodes;
                   IngredientNode ingNode;
                   var node = snapshot.recipeMap[rid];

                   if (!snapshot.ingredientMap.TryGetValue(ingid, out ingNode)) //New ingredient, create node for it
                   {
                  nodes = new List<RecipeNode>[RecipeTag.NUM_TAGS];
                  snapshot.ingredientMap.Add(ingid, ingNode = new IngredientNode()
                  {
                     IngredientId = ingid,
                     RecipesByTag = nodes,
                     ConvType = convType
                  });
                   }
                   else
                   {
                  nodes = ingNode.RecipesByTag as List<RecipeNode>[];
                   }

                   //For each tag the recipe has, we need to create a link through ingNode.RecipesByTag to the recipe
                   if (!node.Hidden) //Don't index Hidden recipes
                   {
                  foreach (var tag in node.Tags)
                  {
                     if (nodes[tag.Value] == null)
                     {
                        nodes[tag.Value] = new List<RecipeNode>();
                     }

                     nodes[tag.Value].Add(node); //Add ingredient link to RecipeNode
                  }
                   }

                   var usages = node.Ingredients as List<IngredientUsage>; //Add ingredient usage to recipe
                   usages.Add(new IngredientUsage()
                   {
                  Amt = qty,
                  Ingredient = ingNode,
                  Unit = unit
                   });
                }

                ModelingSession.Log.InfoFormat("Creating IngredientUsage vertices took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
                timer.Start();

                //Create suggestion links for each recipe
                foreach (var r in snapshot.recipeMap.Values)
                {
                   r.Suggestions = (from s in ratingGraph.GetSimilarRecipes(r.RecipeId) select snapshot.recipeMap[s]).ToArray();
                }

                ModelingSession.Log.InfoFormat("Building suggestions for each recipe took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
            }
示例#14
0
 public BaseItem(IngredientNode iNode)
 {
     ItemName        = iNode.ingredientName;
     ItemDescription = iNode.description;
     ItemValue       = iNode.price;
 }
            public void Index(IKpcContext context)
            {
                var timer = new Stopwatch();
                timer.Start();

                this.ratingGraph = new RatingGraph();
                var loader = context.ModelerLoader;

                foreach (var dataItem in loader.LoadRatingGraph())
                {
                    var rating = dataItem.Rating;
                    var userId = dataItem.UserId;
                    var recipeId = dataItem.RecipeId;

                    if (rating < 4)
                    {
                        continue; // TODO: Might not be needed, DB should only query for 4 or 5 star ratings
                    }

                    this.ratingGraph.AddRating(rating, userId, recipeId);
                }

                ModelingSession.Log.InfoFormat("Building Rating Graph took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
                timer.Start();

                // Create empty recipe nodes without links
                this.snapshot.recipeMap = (from recipeGraph in loader.LoadRecipeGraph()
                                      select new RecipeNode
                                      {
                                          RecipeId = recipeGraph.Id,
                                          Rating = recipeGraph.Rating,
                                          Tags = recipeGraph.Tags,
                                          Hidden = recipeGraph.Hidden,
                                          Ingredients = new List<IngredientUsage>()
                                      }).ToDictionary(k => k.RecipeId);

                ModelingSession.Log.InfoFormat("Building empty RecipeNodes took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
                timer.Start();

                // Build tag index
                foreach (var recipe in this.snapshot.recipeMap.Values)
                {
                    if (recipe.Hidden)
                    {
                        continue; // RecipeList does not include Hidden recipes so they don't get picked at random
                    }

                    foreach (var tag in recipe.Tags)
                    {
                        var nodes = this.snapshot.recipeList[tag.Value] as List<RecipeNode>;
                        if (nodes == null)
                        {
                            this.snapshot.recipeList[tag.Value] = nodes = new List<RecipeNode>();
                        }

                        nodes.Add(recipe);
                    }
                }

                for (var i = 0; i < this.snapshot.recipeList.Length; i++)
                {
                    var list = this.snapshot.recipeList[i] as List<RecipeNode>;
                    if (list != null)
                    {
                        this.snapshot.recipeList[i] = list.ToArray();
                    }
                    else
                    {
                        // No recipes in DB use this tag
                        this.snapshot.recipeList[i] = new RecipeNode[0];
                    }
                }

                ModelingSession.Log.InfoFormat("Indexing recipes by tag took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
                timer.Start();

                // Loop through ingredient usages and fill in vertices on graph
                // For each item: Create IngredientUsage and add to recipe, create IngredientNode (if necessary) and add recipe to IngredientNode
                foreach (var ingredientGraph in loader.LoadIngredientGraph())
                {
                    var recipeId = ingredientGraph.RecipeId;
                    var ingredientId = ingredientGraph.IngredientId;
                    var quantity = ingredientGraph.Quantity;
                    var unit = ingredientGraph.Unit;
                    var convertedType = Unit.GetConvertedType(unit);

                    List<RecipeNode>[] nodes;
                    IngredientNode ingredientNode;
                    var node = this.snapshot.recipeMap[recipeId];

                    if (!this.snapshot.ingredientMap.TryGetValue(ingredientId, out ingredientNode))
                    {
                        // New ingredient, create node for it
                        nodes = new List<RecipeNode>[RecipeTag.NumberOfTags];
                        this.snapshot.ingredientMap.Add(
                            ingredientId,
                            ingredientNode = new IngredientNode { IngredientId = ingredientId, RecipesByTag = nodes, ConvType = convertedType });
                    }
                    else
                    {
                        nodes = ingredientNode.RecipesByTag as List<RecipeNode>[];
                    }

                    // For each tag the recipe has, we need to create a link through ingNode.RecipesByTag to the recipe
                    if (!node.Hidden)
                    {
                        // Don't index Hidden recipes
                        foreach (var tag in node.Tags)
                        {
                            if (nodes[tag.Value] == null)
                            {
                                nodes[tag.Value] = new List<RecipeNode>();
                            }

                            nodes[tag.Value].Add(node); // Add ingredient link to RecipeNode
                        }
                    }

                    var usages = node.Ingredients as List<IngredientUsage>; // Add ingredient usage to recipe
                    usages.Add(new IngredientUsage { Amount = quantity, Ingredient = ingredientNode, Unit = unit });
                }

                ModelingSession.Log.InfoFormat("Creating IngredientUsage vertices took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
                timer.Start();

                // Create suggestion links for each recipe
                foreach (var recipe in this.snapshot.recipeMap.Values)
                {
                    recipe.Suggestions = (from s in this.ratingGraph.GetSimilarRecipes(recipe.RecipeId) select this.snapshot.recipeMap[s]).ToArray();
                }

                ModelingSession.Log.InfoFormat("Building suggestions for each recipe took {0}ms.", timer.ElapsedMilliseconds);
                timer.Reset();
            }