static HelpDef HelpForRecipe( ThingDef thingDef, RecipeDef recipeDef, HelpCategoryDef category )
        {
            var helpDef = new HelpDef();
            helpDef.keyDef = thingDef.defName +"_" + recipeDef.defName;
            helpDef.defName = helpDef.keyDef + "_RecipeDef_Help";
            helpDef.label = recipeDef.label;
            helpDef.category = category;

            var s = new StringBuilder();

            s.AppendLine( recipeDef.description );
            s.AppendLine();

            #region Base Stats

            s.AppendLine( "WorkAmount".Translate() + " : " + GenText.ToStringWorkAmount( recipeDef.WorkAmountTotal( (ThingDef) null ) ) );
            s.AppendLine();

            #endregion

            #region Skill Requirements

            if( ( recipeDef.skillRequirements != null )&&
                ( recipeDef.skillRequirements.Count > 0 ) )
            {
                s.AppendLine( "MinimumSkills".Translate() );
                foreach( var sr in recipeDef.skillRequirements )
                {
                    s.Append( "\t" );
                    s.AppendLine( "BillRequires".Translate( new object[] {
                        sr.minLevel.ToString( "####0" ),
                        sr.skill.label.ToLower()
                    } ) );
                }
                s.AppendLine();
            }

            #endregion

            #region Ingredients

            // List of ingredients
            if( ( recipeDef.ingredients != null )&&
                ( recipeDef.ingredients.Count > 0 ) )
            {
                s.Append( "Ingredients".Translate() );
                s.AppendLine( ":" );
                foreach( var ing in recipeDef.ingredients )
                {
                    if( !GenText.NullOrEmpty( ing.filter.Summary ) )
                    {
                        s.Append( "\t" );
                        s.AppendLine( recipeDef.IngredientValueGetter.BillRequirementsDescription( ing ) );
                    }
                }
                s.AppendLine();
            }

            #endregion

            #region Products

            // List of products
            if( ( recipeDef.products != null )&&
                ( recipeDef.products.Count > 0 ) )
            {
                s.AppendLine( "AutoHelpListRecipeProducts".Translate() );
                foreach( var ing in recipeDef.products )
                {
                    s.Append( "\t" );
                    s.Append( ing.thingDef.LabelCap );
                    s.Append( " : " );
                    s.AppendLine( ing.count.ToString() );
                }
                s.AppendLine();
            }

            #endregion

            #region Things & Research

            // Add things it's on
            var thingDefs = recipeDef.GetThingsCurrent();
            BuildDefDescription( s, "AutoHelpListRecipesOnThings".Translate(), thingDefs.ConvertAll<Def>( def => (Def)def ) );

            // Add research required
            var researchDefs = recipeDef.GetResearchRequirements();
            BuildDefDescription( s, "AutoHelpListResearchRequired".Translate(), researchDefs );

            // What things is it on after research
            thingDefs = recipeDef.GetThingsUnlocked( ref researchDefs );
            BuildDefWithDefDescription( s, "AutoHelpListRecipesOnThingsUnlocked".Translate(), "AutoHelpListResearchBy".Translate(), thingDefs.ConvertAll<Def>( def => (Def)def ), researchDefs.ConvertAll<Def>( def => (Def)def ) );

            // Get research which locks recipe
            thingDefs = recipeDef.GetThingsLocked( ref researchDefs );
            BuildDefWithDefDescription( s, "AutoHelpListRecipesOnThingsLocked".Translate(), "AutoHelpListResearchBy".Translate(), thingDefs.ConvertAll<Def>( def => (Def)def ), researchDefs.ConvertAll<Def>( def => (Def)def ) );

            #endregion

            helpDef.description = s.ToString();
            return helpDef;
        }
        static HelpDef HelpForRecipe( ThingDef thingDef, RecipeDef recipeDef, HelpCategoryDef category )
        {
            var helpDef = new HelpDef();
            helpDef.keyDef = recipeDef;
            helpDef.defName = helpDef.keyDef + "_RecipeDef_Help";
            helpDef.label = recipeDef.label;
            helpDef.category = category;
            helpDef.description = recipeDef.description;

            #region Base Stats

            helpDef.HelpDetailSections.Add( new HelpDetailSection( null, new[] { "WorkAmount".Translate() + " : " + recipeDef.WorkAmountTotal( (ThingDef)null ).ToStringWorkAmount() } ) );

            #endregion

            #region Skill Requirements

            if( !recipeDef.skillRequirements.NullOrEmpty() )
            {
                helpDef.HelpDetailSections.Add( new HelpDetailSection(
                    "MinimumSkills".Translate(),
                    recipeDef.skillRequirements.Select( sr => sr.skill ).ToList().ConvertAll( sd => (Def)sd ),
                    null,
                    recipeDef.skillRequirements.Select( sr => sr.minLevel.ToString( "####0" ) ).ToArray() ) );
            }

            #endregion

            #region Ingredients

            // List of ingredients
            if( !recipeDef.ingredients.NullOrEmpty() )
            {
                // TODO: find the actual thingDefs of ingredients so we can use defs instead of strings.
                HelpDetailSection ingredients = new HelpDetailSection(
                    "Ingredients".Translate(),
                    recipeDef.ingredients.Select(ic => recipeDef.IngredientValueGetter.BillRequirementsDescription( ic )).ToArray());

                helpDef.HelpDetailSections.Add( ingredients );
            }

            #endregion

            #region Products

            // List of products
            if( !recipeDef.products.NullOrEmpty() )
            {
                HelpDetailSection products = new HelpDetailSection(
                    "AutoHelpListRecipeProducts".Translate(),
                    recipeDef.products.Select(tc => tc.thingDef).ToList().ConvertAll(def => (Def)def),
                    recipeDef.products.Select(tc => tc.count.ToString()).ToArray());

                helpDef.HelpDetailSections.Add( products );
            }

            #endregion

            #region Things & Research

            // Add things it's on
            var thingDefs = recipeDef.GetThingsCurrent();
            if( !thingDefs.NullOrEmpty() )
            {
                HelpDetailSection billgivers = new HelpDetailSection(
                    "AutoHelpListRecipesOnThings".Translate(),
                    thingDefs.ConvertAll<Def>(def => (Def)def));

                helpDef.HelpDetailSections.Add( billgivers );
            }

            // Add research required
            var researchDefs = recipeDef.GetResearchRequirements();
            if( !researchDefs.NullOrEmpty() )
            {
                HelpDetailSection requiredResearch = new HelpDetailSection(
                    "AutoHelpListResearchRequired".Translate(),
                    researchDefs);

                helpDef.HelpDetailSections.Add( requiredResearch );
            }

            // What things is it on after research
            thingDefs = recipeDef.GetThingsUnlocked( ref researchDefs );
            if( !thingDefs.NullOrEmpty() )
            {
                HelpDetailSection recipesOnThingsUnlocked = new HelpDetailSection(
                    "AutoHelpListRecipesOnThingsUnlocked".Translate(),
                    thingDefs.ConvertAll<Def>(def => (Def)def));

                helpDef.HelpDetailSections.Add( recipesOnThingsUnlocked );

                if( !researchDefs.NullOrEmpty() )
                {
                    HelpDetailSection researchBy = new HelpDetailSection(
                        "AutoHelpListResearchBy".Translate(),
                        researchDefs.ConvertAll<Def>(def => (Def)def));

                    helpDef.HelpDetailSections.Add( researchBy );
                }
            }

            // Get research which locks recipe
            thingDefs = recipeDef.GetThingsLocked( ref researchDefs );
            if( !thingDefs.NullOrEmpty() )
            {
                HelpDetailSection recipesOnThingsLocked = new HelpDetailSection(
                    "AutoHelpListRecipesOnThingsLocked".Translate(),
                    thingDefs.ConvertAll<Def>(def => (Def)def));

                helpDef.HelpDetailSections.Add( recipesOnThingsLocked );

                if( !researchDefs.NullOrEmpty() )
                {
                    HelpDetailSection researchBy = new HelpDetailSection(
                        "AutoHelpListResearchBy".Translate(),
                        researchDefs.ConvertAll<Def>(def => (Def)def));

                    helpDef.HelpDetailSections.Add( researchBy );
                }
            }

            #endregion

            return helpDef;
        }