text:
package com.drmilk.nbawrapper.domain;

import java.util.List;

import com.drmilk.nbawrapper.domain.utils.boxscore.Boxscore;
import com.drmilk.nbawrapper.domain.utils.scoreboard.GameDetails;
import com.drmilk.nbawrapper.domain.utils.scoreboard.Scoreboard;
import com.drmilk.nbawrapper.exception.BoxscoreNotFoundException;
import com.drmilk.nbawrapper.exception.ScoreboardNotFoundException;

import junit.framework.Assert;
import junit.framework.TestCase;

public class LeagueTest extends TestCase {

	public void testGetValidScoreboard() throws ScoreboardNotFoundException {
		Scoreboard league = League.getScoreboard("25", "12", "2016");
		Assert.assertNotNull(league);
		List<GameDetails> gameList = league.getGames();
		Assert.assertEquals(5, gameList.size());
		Assert.assertEquals(new Integer(5), league.getNumGames());
		boolean cavsWarGameFoud = false;
		for (GameDetails game : gameList) {
			if (game.getHomeTeamScore().getTriCode().equals("CLE")
					&& game.getVisitingTeamScore().getTriCode().equals("GSW")) {
				cavsWarGameFoud = true;
				break;
			}
		}
		Assert.assertTrue(cavsWarGameFoud);
	}

	public void testGetValidBoxscore() throws BoxscoreNotFoundException {
		Boxscore boxscore = League.getBoxscore("25", "12", "2016", "0021600457");
		Assert.assertNotNull(boxscore);
		Assert.assertEquals("109", boxscore.getBasicGameData().getHomeTeam().getScore());
		Assert.assertEquals("108", boxscore.getBasicGameData().getVisitingTeam().getScore());
	}
}


text:
**LinkIt** is a simple Jquery Plugin to attach links to elements.

## Version ##

0.2.0

##Usage##
	$("span").linkIt({
		href: "http://test.com",
		text: "click me",
		target: "_blank"
	});

##Vendors##

JQuery -[http://jquery.com](http://Jquery.com)

##Lincence##

MIT Licence

redpajama_set_name: RedPajamaGithub


text:
typedef NS_ENUM(NSInteger, STPBackendChargeResult) {
    STPBackendChargeResultSuccess,
    STPBackendChargeResultFailure,
};

typedef void (^STPTokenSubmissionHandler)(STPBackendChargeResult status, NSError *error);

@protocol STPBackendCharging <NSObject>

- (void)createBackendChargeWithToken:(STPToken *)token completion:(STPTokenSubmissionHandler)completion;

@end

@interface ViewController : UIViewController<STPBackendCharging>

@end


text:
Originally published: 2003-09-30 05:32:54
Last updated: 2003-09-30 05:32:54
Author: gyro funch

This recipe uses a regular expression to determine whether or not the argument to the function is in a numeric format (integer, floating point, scientific, or engineering).


text:
module Signal
  Names = {
    "EXIT" => 0
  }

  Numbers = {
    0 => "EXIT"
  }

  @threads = {}
  @handlers = {}

  def self.trap(sig, prc=nil, &block)
    sig = sig.to_s if sig.kind_of?(Symbol)

    if sig.kind_of?(String)
      osig = sig

      if sig.prefix? "SIG"
        sig = sig[3..-1]
      end

      unless number = Names[sig]
        raise ArgumentError, "Unknown signal '#{osig}'"
      end
    else
      number = sig.to_i
    end

    # If no command, use the block.
    prc ||= block
    prc = prc.to_s if prc.kind_of?(Symbol)

    case prc
    when "DEFAULT", "SIG_DFL"
      had_old = @handlers.key?(number)
      old = @handlers.delete(number)

      if number != Names["EXIT"]
        Rubinius.watch_signal(-number, prc.nil? || prc == 'IGNORE')
      end

      return "DEFAULT" unless had_old
      return old ? old : nil
    when "IGNORE", "SIG_IGN"
      prc = "IGNORE"
    when nil
      prc = nil
    when "EXIT"
      prc = proc { exit }
    when String
      raise ArgumentError, "Unsupported command '#{prc}'"
    else
      unless prc.respond_to? :call
        raise ArgumentError, "Handler must respond to #call (was #{prc.class})"
      end
    end

    had_old = @handlers.key?(number)

    old = @handlers[number]
    @handlers[number] = prc

    if number != Names["EXIT"]
      Rubinius.watch_signal(number, prc.nil? || prc == 'IGNORE')
    end

    return "DEFAULT" unless had_old
    return old ? old : nil
  end

  def self.run_handler(sig)
    # Ignore nil handlers
    if handler = @handlers[sig]
      handler.call(sig)
    end
  end

  def self.list
    Names.dup
  end
end


text:
<?php

namespace AppVentus\AviaryBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
 * This is the class that validates and merges configuration from your app/config files
 *
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
 */
class Configuration implements ConfigurationInterface
{
    /**
     * {@inheritDoc}
     */
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root('aviary');

        $rootNode
            ->children()
                ->scalarNode('upload_dir')->defaultValue("%kernel.root_dir%/../web/uploads/gallery/")->end()
            ->end()
            ->children()
                ->scalarNode('upload_url')->defaultValue("/uploads/gallery/")->end()
            ->end()
            ->children()
                ->scalarNode('user_dirs')->defaultFalse()->end()
            ->end()
            ->children()
                ->scalarNode('mkdir_mode')->defaultValue("0755")->end()
            ->end()
            ->children()
                ->scalarNode('param_name')->defaultValue("files")->end()
            ->end()
            ->children()
                // Set the following option to 'POST', if your server does not support
                // DELETE requests. This is a parameter sent to the client:
                ->scalarNode('delete_type')->defaultValue("DELETE")->end()
            ->end()
            ->children()
                ->scalarNode('access_control_allow_origin')->defaultValue("*")->end()
            ->end()
            ->children()
                ->scalarNode('access_control_allow_credentials')->defaultFalse()->end()
            ->end()
            ->children()
                ->variableNode('access_control_allow_methods')
                    ->defaultValue(array(
                        'OPTIONS',
                        'HEAD',
                        'GET',
                        'POST',
                        'PUT',
                        'PATCH',
                        'DELETE'
                    ))
                ->end()
            ->end()
            ->children()
                ->variableNode('access_control_allow_headers')
                    ->defaultValue(array(
                        'Content-Type',
                        'Content-Range',
                        'Content-Disposition'
                    ))
                ->end()
            ->end()
            // Enable to provide file downloads via GET requests to the PHP script:
            //     1. Set to 1 to download files via readfile method through PHP
            //     2. Set to 2 to send a X-Sendfile header for lighttpd/Apache
            //     3. Set to 3 to send a X-Accel-Redirect header for nginx
            // If set to 2 or 3, adjust the upload_url option to the base path of
            // the redirect parameter, e.g. '/files/'.
            ->children()
                ->scalarNode('download_via_php')->defaultValue(false)->end()
            ->end()
            // Read files in chunks to avoid memory limits when download_via_php
            // is enabled, set to 0 to disable chunked reading of files:
            ->children()
                ->scalarNode('readfile_chunk_size')->defaultValue(10 * 1024 * 1024)->end()
            ->end()
            // Defines which files can be displayed inline when downloaded:
            ->children()
                ->scalarNode('inline_file_types')->defaultValue('/\.(gif|jpe?g|png)$/i')->end()
            ->end()
            // Defines which files (based on their names) are accepted for upload:
            ->children()
                ->scalarNode('accept_file_types')->defaultValue('/.+$/i')->end()
            ->end()
            ->children()
                ->scalarNode('max_file_size')->defaultNull()->end()
            ->end()
            ->children()
                ->scalarNode('min_file_size')->defaultValue(1)->end()
            ->end()
            // The php.ini settings upload_max_filesize and post_max_size
            // take precedence over the following max_file_size setting:
            ->children()
                ->scalarNode('max_number_of_files')->defaultNull()->end()
            ->end()
            // Defines which files are handled as image files:
            ->children()
                ->scalarNode('image_file_types')->defaultValue('/\.(gif|jpe?g|png)$/i')->end()
            ->end()
            // Image resolution restrictions:
            ->children()
                ->scalarNode('max_width')->defaultNull()->end()
            ->end()
            ->children()
                ->scalarNode('max_height')->defaultNull()->end()
            ->end()
            ->children()
                ->scalarNode('min_width')->defaultValue(1)->end()
            ->end()
            ->children()
                ->scalarNode('min_height')->defaultValue(1)->end()
            ->end()
            // Set the following option to false to enable resumable uploads:
            ->children()
                ->scalarNode('discard_aborted_uploads')->defaultValue(true)->end()
            ->end()
            // Set to 0 to use the GD library to scale and orient images,
            // set to 1 to use imagick (if installed, falls back to GD),
            // set to 2 to use the ImageMagick convert binary directly:
            ->children()
                ->scalarNode('image_library')->defaultValue(1)->end()
            ->end()
            // Uncomment the following to define an array of resource limits
            // for imagick:
            ->children()
                ->variableNode('imagick_resource_limits')->defaultValue(array(
                    // imagick::RESOURCETYPE_MAP => 32,
                    // imagick::RESOURCETYPE_MEMORY => 32
            ))->end()
            ->end()
            // Command or path for to the ImageMagick convert binary:
            ->children()
                ->scalarNode('convert_bin')->defaultValue('convert')->end()
            ->end()
            // Uncomment the following to add parameters in front of each
            // ImageMagick convert call (the limit constraints seem only
            // to have an effect if put in front):
            ->children()
                ->scalarNode('convert_params')->defaultValue('-limit memory 32MiB -limit map 32MiB')->end()
            ->end()
            // Command or path for to the ImageMagick identify binary:
            ->children()
                ->scalarNode('identify_bin')->defaultValue('identify')->end()
            ->end()
            ->children()
                ->arrayNode('image_versions')
                    ->prototype('array')
                        ->children()
                            ->scalarNode('auto_orient')->end()
                            ->scalarNode('max_width')->end()
                            ->scalarNode('max_height')->end()
                            ->scalarNode('upload_dir')->end()
                            ->scalarNode('upload_url')->end()
                        ->end()
                    ->end()
                ->end()
            ->end();

        // Here you should define the parameters that are allowed to
        // configure your bundle. See the documentation linked above for
        // more information on that topic.
        return $treeBuilder;
    }
}


text:
package com.andfast.statusbar;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.Toolbar;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;

import java.lang.reflect.Field;

@TargetApi(Build.VERSION_CODES.KITKAT)
class EyesKitKat {
    private static final String TAG_FAKE_STATUS_BAR_VIEW = "statusBarView";
    private static final String TAG_MARGIN_ADDED = "marginAdded";

    static void setStatusBarColor(Activity activity, int statusColor) {
        Window window = activity.getWindow();
        //设置Window为全透明
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
        //获取父布局
        View mContentChild = mContentView.getChildAt(0);
        //获取状态栏高度
        int statusBarHeight = getStatusBarHeight(activity);

        //如果已经存在假状态栏则移除,防止重复添加
        removeFakeStatusBarViewIfExist(activity);
        //添加一个View来作为状态栏的填充
        addFakeStatusBarView(activity, statusColor, statusBarHeight);
        //设置子控件到状态栏的间距
        addMarginTopToContentChild(mContentChild, statusBarHeight);
        //不预留系统栏位置
        if (mContentChild != null) {
            ViewCompat.setFitsSystemWindows(mContentChild, false);
        }
        //如果在Activity中使用了ActionBar则需要再将布局与状态栏的高度跳高一个ActionBar的高度,否则内容会被ActionBar遮挡
        int action_bar_id = activity.getResources().getIdentifier("action_bar", "id", activity.getPackageName());
        View view = activity.findViewById(action_bar_id);
        if (view != null) {
           TypedValue typedValue = new TypedValue();
            if (activity.getTheme().resolveAttribute(R.attr.actionBarSize, typedValue, true)) {
                int actionBarHeight = TypedValue.complexToDimensionPixelSize(typedValue.data, activity.getResources().getDisplayMetrics());
                Eyes.setContentTopPadding(activity, actionBarHeight);
            }
        }
    }

    static void translucentStatusBar(Activity activity) {
        Window window = activity.getWindow();
        //设置Window为透明
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
        View mContentChild = mContentView.getChildAt(0);

        //移除已经存在假状态栏则,并且取消它的Margin间距
        removeFakeStatusBarViewIfExist(activity);
        removeMarginTopOfContentChild(mContentChild, getStatusBarHeight(activity));
        if (mContentChild != null) {
            //fitsSystemWindow 为 false, 不预留系统栏位置.
            ViewCompat.setFitsSystemWindows(mContentChild, false);
        }
    }

    static void setStatusBarColorForCollapsingToolbar(Activity activity, final AppBarLayout appBarLayout, final CollapsingToolbarLayout collapsingToolbarLayout,
                                                      Toolbar toolbar, int statusColor) {
        Window window = activity.getWindow();
        //设置Window为全透明
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);

        //AppBarLayout,CollapsingToolbarLayout,ToolBar,ImageView的fitsSystemWindow统一改为false, 不预留系统栏位置.
        View mContentChild = mContentView.getChildAt(0);
        mContentChild.setFitsSystemWindows(false);
        ((View) appBarLayout.getParent()).setFitsSystemWindows(false);
        appBarLayout.setFitsSystemWindows(false);
        collapsingToolbarLayout.setFitsSystemWindows(false);
        collapsingToolbarLayout.getChildAt(0).setFitsSystemWindows(false);

        toolbar.setFitsSystemWindows(false);
        //为Toolbar添加一个状态栏的高度, 同时为Toolbar添加paddingTop,使Toolbar覆盖状态栏,ToolBar的title可以正常显示.
        if (toolbar.getTag() == null) {
            CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) toolbar.getLayoutParams();
            int statusBarHeight = getStatusBarHeight(activity);
            lp.height += statusBarHeight;
            toolbar.setLayoutParams(lp);
            toolbar.setPadding(toolbar.getPaddingLeft(), toolbar.getPaddingTop() + statusBarHeight, toolbar.getPaddingRight(), toolbar.getPaddingBottom());
            toolbar.setTag(true);
        }
        //移除已经存在假状态栏则,并且取消它的Margin间距
        int statusBarHeight = getStatusBarHeight(activity);
        removeFakeStatusBarViewIfExist(activity);
        removeMarginTopOfContentChild(mContentChild, statusBarHeight);
        //添加一个View来作为状态栏的填充
        final View statusView = addFakeStatusBarView(activity, statusColor, statusBarHeight);

        CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).getBehavior();
        if (behavior != null && behavior instanceof AppBarLayout.Behavior) {
            int verticalOffset = ((AppBarLayout.Behavior) behavior).getTopAndBottomOffset();
            if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
                statusView.setAlpha(1f);
            } else {
                statusView.setAlpha(0f);
            }
        } else {
            statusView.setAlpha(0f);
        }
        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
                    //toolbar被折叠时显示状态栏
                    if (statusView.getAlpha() == 0) {
                        statusView.animate().cancel();
                        statusView.animate().alpha(1f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
                    }
                } else {
                    //toolbar展开时显示状态栏
                    if (statusView.getAlpha() == 1) {
                        statusView.animate().cancel();
                        statusView.animate().alpha(0f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
                    }
                }
            }
        });
    }

    static void setStatusBarWhiteForCollapsingToolbar(final Activity activity, AppBarLayout appBarLayout, final CollapsingToolbarLayout collapsingToolbarLayout, Toolbar toolbar, final int statusBarColor) {
        final Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT);
        View mContentChild = mContentView.getChildAt(0);
        mContentChild.setFitsSystemWindows(false);
        ((View) appBarLayout.getParent()).setFitsSystemWindows(false);
        appBarLayout.setFitsSystemWindows(false);
        collapsingToolbarLayout.setFitsSystemWindows(false);
        collapsingToolbarLayout.getChildAt(0).setFitsSystemWindows(false);
        toolbar.setFitsSystemWindows(false);

        if (toolbar.getTag() == null) {
            CollapsingToolbarLayout.LayoutParams lp = (CollapsingToolbarLayout.LayoutParams) toolbar.getLayoutParams();
            int statusBarHeight = getStatusBarHeight(activity);
            lp.height += statusBarHeight;
            toolbar.setLayoutParams(lp);
            toolbar.setPadding(toolbar.getPaddingLeft(), toolbar.getPaddingTop() + statusBarHeight, toolbar.getPaddingRight(), toolbar.getPaddingBottom());
            toolbar.setTag(true);
        }

        int statusBarHeight = getStatusBarHeight(activity);
        int color = Color.BLACK;
        try {
            Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
            color = statusBarColor;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        try {
            Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
            color = statusBarColor;
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        final View statusView = addFakeStatusBarView(activity, color, statusBarHeight);
        CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams()).getBehavior();
        if (behavior != null && behavior instanceof AppBarLayout.Behavior) {
            int verticalOffset = ((AppBarLayout.Behavior) behavior).getTopAndBottomOffset();
            if (Math.abs(verticalOffset) > appBarLayout.getHeight() - collapsingToolbarLayout.getScrimVisibleHeightTrigger()) {
                statusView.setAlpha(1f);
            } else {
                statusView.setAlpha(0f);
            }
        } else {
            statusView.setAlpha(0f);
        }

        appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            private final static int EXPANDED = 0;
            private final static int COLLAPSED = 1;
            private int appBarLayoutState;

            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
                if (Math.abs(verticalOffset) >= (appBarLayout.getTotalScrollRange() - Eyes.getPxFromDp(activity, 56))) {
                    if (appBarLayoutState != COLLAPSED) {
                        appBarLayoutState = COLLAPSED;

                        if (Eyes.MIUISetStatusBarLightMode(activity, true) || Eyes.FlymeSetStatusBarLightMode(activity, true)) {
                        }
                        if (statusView.getAlpha() == 0) {
                            statusView.animate().cancel();
                            statusView.animate().alpha(1f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
                        }
                    }
                } else {
                    if (appBarLayoutState != EXPANDED) {
                        appBarLayoutState = EXPANDED;

                        if (Eyes.MIUISetStatusBarLightMode(activity, false) || Eyes.FlymeSetStatusBarLightMode(activity, false)) {
                        }
                        if (statusView.getAlpha() == 1) {
                            statusView.animate().cancel();
                            statusView.animate().alpha(0f).setDuration(collapsingToolbarLayout.getScrimAnimationDuration()).start();
                        }
                    }
                }
            }
        });
    }

    private static void removeFakeStatusBarViewIfExist(Activity activity) {
        Window window = activity.getWindow();
        ViewGroup mDecorView = (ViewGroup) window.getDecorView();

        View fakeView = mDecorView.findViewWithTag(TAG_FAKE_STATUS_BAR_VIEW);
        if (fakeView != null) {
            mDecorView.removeView(fakeView);
        }
    }

    private static View addFakeStatusBarView(Activity activity, int statusBarColor, int statusBarHeight) {
        Window window = activity.getWindow();
        ViewGroup mDecorView = (ViewGroup) window.getDecorView();

        View mStatusBarView = new View(activity);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, statusBarHeight);
        layoutParams.gravity = Gravity.TOP;
        mStatusBarView.setLayoutParams(layoutParams);
        mStatusBarView.setBackgroundColor(statusBarColor);
        mStatusBarView.setTag(TAG_FAKE_STATUS_BAR_VIEW);

        mDecorView.addView(mStatusBarView);
        return mStatusBarView;
    }

    private static void addMarginTopToContentChild(View mContentChild, int statusBarHeight) {
        if (mContentChild == null) {
            return;
        }
        if (!TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
            lp.topMargin += statusBarHeight;
            mContentChild.setLayoutParams(lp);
            mContentChild.setTag(TAG_MARGIN_ADDED);
        }
    }

    private static int getStatusBarHeight(Context context) {
        int result = 0;
        int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resId > 0) {
            result = context.getResources().getDimensionPixelOffset(resId);
        }
        return result;
    }

    private static void removeMarginTopOfContentChild(View mContentChild, int statusBarHeight) {
        if (mContentChild == null) {
            return;
        }
        if (TAG_MARGIN_ADDED.equals(mContentChild.getTag())) {
            FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mContentChild.getLayoutParams();
            lp.topMargin -= statusBarHeight;
            mContentChild.setLayoutParams(lp);
            mContentChild.setTag(null);
        }
    }

}


text:
#ifndef _SCREENCULL_HPP_
#define _SCREENCULL_HPP_

#include <Cull.hpp>
#include <map>
#include <Config.hpp>

namespace ooge
{
	class Renderable;
	class Camera;

	class OOGE_API ScreenCull : public Cull
	{
	public:
		ScreenCull(const std::string &name);

		virtual bool CheckRenderable(Renderable *renderable);
	};
}

#endif //_SCREENCULL_HPP_


text:
namespace operations_research {
namespace math_opt {

std::optional<absl::string_view> Enum<SolutionStatus>::ToOptString(
    SolutionStatus value) {
  switch (value) {
    case SolutionStatus::kFeasible:
      return "feasible";
    case SolutionStatus::kInfeasible:
      return "infeasible";
    case SolutionStatus::kUndetermined:
      return "undetermined";
  }
  return std::nullopt;
}

absl::Span<const SolutionStatus> Enum<SolutionStatus>::AllValues() {
  static constexpr SolutionStatus kSolutionStatusValues[] = {
      SolutionStatus::kFeasible,
      SolutionStatus::kInfeasible,
      SolutionStatus::kUndetermined,
  };
  return absl::MakeConstSpan(kSolutionStatusValues);
}

absl::StatusOr<PrimalSolution> PrimalSolution::FromProto(
    const ModelStorage* model,
    const PrimalSolutionProto& primal_solution_proto) {
  PrimalSolution primal_solution;
  OR_ASSIGN_OR_RETURN3(
      primal_solution.variable_values,
      VariableValuesFromProto(model, primal_solution_proto.variable_values()),
      _ << "invalid variable_values");
  primal_solution.objective_value = primal_solution_proto.objective_value();
  const std::optional<SolutionStatus> feasibility_status =
      EnumFromProto(primal_solution_proto.feasibility_status());
  if (!feasibility_status.has_value()) {
    return absl::InvalidArgumentError("feasibility_status must be specified");
  }
  primal_solution.feasibility_status = *feasibility_status;
  return primal_solution;
}

PrimalSolutionProto PrimalSolution::Proto() const {
  PrimalSolutionProto result;
  *result.mutable_variable_values() = VariableValuesToProto(variable_values);
  result.set_objective_value(objective_value);
  result.set_feasibility_status(EnumToProto(feasibility_status));
  return result;
}

absl::StatusOr<PrimalRay> PrimalRay::FromProto(
    const ModelStorage* model, const PrimalRayProto& primal_ray_proto) {
  PrimalRay result;
  OR_ASSIGN_OR_RETURN3(
      result.variable_values,
      VariableValuesFromProto(model, primal_ray_proto.variable_values()),
      _ << "invalid variable_values");
  return result;
}

PrimalRayProto PrimalRay::Proto() const {
  PrimalRayProto result;
  *result.mutable_variable_values() = VariableValuesToProto(variable_values);
  return result;
}

absl::StatusOr<DualSolution> DualSolution::FromProto(
    const ModelStorage* model, const DualSolutionProto& dual_solution_proto) {
  DualSolution dual_solution;
  OR_ASSIGN_OR_RETURN3(
      dual_solution.dual_values,
      LinearConstraintValuesFromProto(model, dual_solution_proto.dual_values()),
      _ << "invalid dual_values");
  OR_ASSIGN_OR_RETURN3(
      dual_solution.reduced_costs,
      VariableValuesFromProto(model, dual_solution_proto.reduced_costs()),
      _ << "invalid reduced_costs");
  if (dual_solution_proto.has_objective_value()) {
    dual_solution.objective_value = dual_solution_proto.objective_value();
  }
  const std::optional<SolutionStatus> feasibility_status =
      EnumFromProto(dual_solution_proto.feasibility_status());
  if (!feasibility_status.has_value()) {
    return absl::InvalidArgumentError("feasibility_status must be specified");
  }
  dual_solution.feasibility_status = *feasibility_status;
  return dual_solution;
}

DualSolutionProto DualSolution::Proto() const {
  DualSolutionProto result;
  *result.mutable_dual_values() = LinearConstraintValuesToProto(dual_values);
  *result.mutable_reduced_costs() = VariableValuesToProto(reduced_costs);
  if (objective_value.has_value()) {
    result.set_objective_value(*objective_value);
  }
  result.set_feasibility_status(EnumToProto(feasibility_status));
  return result;
}

absl::StatusOr<DualRay> DualRay::FromProto(const ModelStorage* model,
                                           const DualRayProto& dual_ray_proto) {
  DualRay result;
  OR_ASSIGN_OR_RETURN3(
      result.dual_values,
      LinearConstraintValuesFromProto(model, dual_ray_proto.dual_values()),
      _ << "invalid dual_values");
  OR_ASSIGN_OR_RETURN3(
      result.reduced_costs,
      VariableValuesFromProto(model, dual_ray_proto.reduced_costs()),
      _ << "invalid reduced_costs");
  return result;
}

DualRayProto DualRay::Proto() const {
  DualRayProto result;
  *result.mutable_dual_values() = LinearConstraintValuesToProto(dual_values);
  *result.mutable_reduced_costs() = VariableValuesToProto(reduced_costs);
  return result;
}

absl::StatusOr<Basis> Basis::FromProto(const ModelStorage* model,
                                       const BasisProto& basis_proto) {
  Basis basis;
  OR_ASSIGN_OR_RETURN3(
      basis.constraint_status,
      LinearConstraintBasisFromProto(model, basis_proto.constraint_status()),
      _ << "invalid constraint_status");
  OR_ASSIGN_OR_RETURN3(
      basis.variable_status,
      VariableBasisFromProto(model, basis_proto.variable_status()),
      _ << "invalid variable_status");
  const std::optional<SolutionStatus> basic_dual_feasibility =
      EnumFromProto(basis_proto.basic_dual_feasibility());
  if (!basic_dual_feasibility.has_value()) {
    return absl::InvalidArgumentError(
        "basic_dual_feasibility for a basis must be specified");
  }
  basis.basic_dual_feasibility = *basic_dual_feasibility;
  return basis;
}

BasisProto Basis::Proto() const {
  BasisProto result;
  *result.mutable_constraint_status() =
      LinearConstraintBasisToProto(constraint_status);
  *result.mutable_variable_status() = VariableBasisToProto(variable_status);
  result.set_basic_dual_feasibility(EnumToProto(basic_dual_feasibility));
  return result;
}

absl::StatusOr<Solution> Solution::FromProto(
    const ModelStorage* model, const SolutionProto& solution_proto) {
  Solution solution;
  if (solution_proto.has_primal_solution()) {
    OR_ASSIGN_OR_RETURN3(
        solution.primal_solution,
        PrimalSolution::FromProto(model, solution_proto.primal_solution()),
        _ << "invalid primal_solution");
  }
  if (solution_proto.has_dual_solution()) {
    OR_ASSIGN_OR_RETURN3(
        solution.dual_solution,
        DualSolution::FromProto(model, solution_proto.dual_solution()),
        _ << "invalid dual_solution");
  }
  if (solution_proto.has_basis()) {
    OR_ASSIGN_OR_RETURN3(solution.basis,
                         Basis::FromProto(model, solution_proto.basis()),
                         _ << "invalid basis");
  }
  return solution;
}

SolutionProto Solution::Proto() const {
  SolutionProto result;
  if (primal_solution.has_value()) {
    *result.mutable_primal_solution() = primal_solution->Proto();
  }
  if (dual_solution.has_value()) {
    *result.mutable_dual_solution() = dual_solution->Proto();
  }
  if (basis.has_value()) {
    *result.mutable_basis() = basis->Proto();
  }
  return result;
}

}  // namespace math_opt
}  // namespace operations_research


text:
package kujiin.util.enums;

public enum IconDisplayType {
    ICONS_ONLY, TEXT_ONLY, ICONS_AND_TEXT

}


text:
<?xml version="1.0" encoding="UTF-8"?>
<catalog name="gsbsc-chain-catalog">

	<!-- KPI tree items 資料產生用的 chain -->
	<chain name="kpiTreeItemsChain">
		<command id="LoadBscMixDataCommand" 		className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 		className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="ProcessBscTreeItemsCommand" 	className="com.netsteadfast.greenstep.bsc.command.ProcessBscTreeItemsCommand"/>
	</chain>

	<!-- WEIGHT 權重設定資料產生用的 chain -->
	<chain name="weightItemsChain">
		<command id="LoadBscMixDataCommand" 		className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 		className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="WeightBodyCommand" 			className="com.netsteadfast.greenstep.bsc.command.WeightBodyCommand"/>
	</chain>

	<!-- 績效分數資料產生用的 chain -->
	<chain name="performanceScoreChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 			className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiDateRangeScoreCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiDateRangeScoreCommand"/>
		<command id="ParentItemDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.ParentItemDateRangeScoreCommand"/>
	</chain>

	<!-- KPI報表html版產生內容用的 chain -->
	<chain name="kpiReportHtmlContentChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 			className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiDateRangeScoreCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiDateRangeScoreCommand"/>
		<command id="ParentItemDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.ParentItemDateRangeScoreCommand"/>
		<command id="KpiReportBodyCommand" 				className="com.netsteadfast.greenstep.bsc.command.KpiReportBodyCommand"/>
	</chain>

	<!-- KPI報表Excel版產生內容用的 chain -->
	<chain name="kpiReportExcelContentChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 			className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiDateRangeScoreCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiDateRangeScoreCommand"/>
		<command id="ParentItemDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.ParentItemDateRangeScoreCommand"/>
		<command id="KpiReportExcelCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiReportExcelCommand"/>
	</chain>

	<!-- KPI報表PDF版產生內容用的 chain -->
	<chain name="kpiReportPdfContentChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 			className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiDateRangeScoreCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiDateRangeScoreCommand"/>
		<command id="ParentItemDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.ParentItemDateRangeScoreCommand"/>
		<command id="KpiReportPdfCommand" 				className="com.netsteadfast.greenstep.bsc.command.KpiReportPdfCommand"/>
	</chain>

	<!-- KPI報表 coffeeChart json 資料產生內容用的 chain -->
	<chain name="kpiReportCoffeeChartJsonDataContentChain">
		<command id="LoadBscMixDataCommand" 				className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 				className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 				className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 				className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiReportCoffeeChartJsonDataCommand"	className="com.netsteadfast.greenstep.bsc.command.KpiReportCoffeeChartJsonDataCommand"/>
	</chain>

	<!-- 個人報表html版產生內容用的 chain -->
	<chain name="personalReportHtmlContentChain">
		<command id="LoadBscMixDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 								className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="PersonalAndOrganizationReportDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.PersonalAndOrganizationReportDateRangeScoreCommand"/>
		<command id="PersonalReportBodyCommand" 							className="com.netsteadfast.greenstep.bsc.command.PersonalReportBodyCommand"/>
	</chain>

	<!-- 個人報表Excel版產生內容用的 chain -->
	<chain name="personalReportExcelContentChain">
		<command id="LoadBscMixDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 								className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="PersonalAndOrganizationReportDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.PersonalAndOrganizationReportDateRangeScoreCommand"/>
		<command id="PersonalReportExcelCommand" 							className="com.netsteadfast.greenstep.bsc.command.PersonalReportExcelCommand"/>
	</chain>

	<!-- 個人報表PDF版產生內容用的 chain -->
	<chain name="personalReportPdfContentChain">
		<command id="LoadBscMixDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 								className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="PersonalAndOrganizationReportDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.PersonalAndOrganizationReportDateRangeScoreCommand"/>
		<command id="PersonalReportPdfCommand" 								className="com.netsteadfast.greenstep.bsc.command.PersonalReportPdfCommand"/>
	</chain>

	<!-- 部門報表html版產生內容用的 chain -->
	<chain name="organizationReportHtmlContentChain">
		<command id="LoadBscMixDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 								className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="PersonalAndOrganizationReportDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.PersonalAndOrganizationReportDateRangeScoreCommand"/>
		<command id="OrganizationReportBodyCommand" 						className="com.netsteadfast.greenstep.bsc.command.OrganizationReportBodyCommand"/>
	</chain>

	<!-- 部門報表Excel版產生內容用的 chain -->
	<chain name="organizationReportExcelContentChain">
		<command id="LoadBscMixDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 								className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="PersonalAndOrganizationReportDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.PersonalAndOrganizationReportDateRangeScoreCommand"/>
		<command id="OrganizationReportExcelCommand" 						className="com.netsteadfast.greenstep.bsc.command.OrganizationReportExcelCommand"/>
	</chain>

	<!-- 部門報表PDF版產生內容用的 chain -->
	<chain name="organizationReportPdfContentChain">
		<command id="LoadBscMixDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 								className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 								className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="PersonalAndOrganizationReportDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.PersonalAndOrganizationReportDateRangeScoreCommand"/>
		<command id="OrganizationReportPdfCommand" 							className="com.netsteadfast.greenstep.bsc.command.OrganizationReportPdfCommand"/>
	</chain>

	<!-- 策略地圖資料產生用的 chain -->
	<chain name="strategyMapItemsForNewChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadStrategyMapItemsForNewCommand"	className="com.netsteadfast.greenstep.bsc.command.LoadStrategyMapItemsForNewCommand"/>
	</chain>

	<!-- 策略地圖資料產生用的 chain -->
	<!--
	讀取策略地圖資料 BB_STRATEGY_MAP, BB_STRATEGY_MAP_NODES, BB_STRATEGY_MAP_CONNS 並不需要 LoadBscMixDataCommand 與 LoadBscStructTreeCommand
	但願景Vision 之下沒有 Perspectives, Objective, KPI 本來就不因該有策略地圖
	 -->
	<chain name="strategyMapItemsForRecChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadStrategyMapItemsForRecCommand"	className="com.netsteadfast.greenstep.bsc.command.LoadStrategyMapItemsForRecCommand"/>
	</chain>

	<!-- SWOT頁面產生的 chain -->
	<chain name="swotHtmlContentChain">
		<command id="SwotDataProvideCommand" 	className="com.netsteadfast.greenstep.bsc.command.SwotDataProvideCommand"/>
		<command id="SwotBodyCommand" 			className="com.netsteadfast.greenstep.bsc.command.SwotBodyCommand"/>
	</chain>

	<!-- SWOT報表Jasperreport PDF 產生要用資料的 chain -->
	<!--
	產生 BB_SWOT_REPORT_MST, BB_SWOT_REPORT_DTL 資料
	 -->
	<chain name="swotPdfDataContentChain">
		<command id="SwotDataProvideCommand" 	className="com.netsteadfast.greenstep.bsc.command.SwotDataProvideCommand"/>
		<command id="SwotReportPdfDataCommand" 	className="com.netsteadfast.greenstep.bsc.command.SwotReportPdfDataCommand"/>
	</chain>

	<!-- Perspectives Dashboard 輸出 Excel 產生用的 chain -->
	<chain name="perspectivesDashboardExcelContentChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 			className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiDateRangeScoreCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiDateRangeScoreCommand"/>
		<command id="ParentItemDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.ParentItemDateRangeScoreCommand"/>
		<command id="PerspectivesDashboardExcelCommand"		className="com.netsteadfast.greenstep.bsc.command.PerspectivesDashboardExcelCommand"/>
	</chain>

	<!-- Objectives Dashboard 輸出 Excel 產生用的 chain -->
	<chain name="objectivesDashboardExcelContentChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 			className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiDateRangeScoreCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiDateRangeScoreCommand"/>
		<command id="ParentItemDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.ParentItemDateRangeScoreCommand"/>
		<command id="ObjectivesDashboardExcelCommand"		className="com.netsteadfast.greenstep.bsc.command.ObjectivesDashboardExcelCommand"/>
	</chain>

	<!-- KPIs Dashboard 輸出 Excel 產生用的 chain -->
	<chain name="kpisDashboardExcelContentChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 			className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiDateRangeScoreCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiDateRangeScoreCommand"/>
		<command id="ParentItemDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.ParentItemDateRangeScoreCommand"/>
		<command id="KpisDashboardExcelCommand"				className="com.netsteadfast.greenstep.bsc.command.KpisDashboardExcelCommand"/>
	</chain>

	<!-- Dashboard 輸出 Excel 產生用的 chain -->
	<chain name="dashboardNewExcelContentChain">
		<command id="LoadBscMixDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscMixDataCommand"/>
		<command id="LoadBscStructTreeCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadBscStructTreeCommand"/>
		<command id="LoadMeasureDataCommand" 			className="com.netsteadfast.greenstep.bsc.command.LoadMeasureDataCommand"/>
		<command id="ScoreCalculationCommand" 			className="com.netsteadfast.greenstep.bsc.command.ScoreCalculationCommand"/>
		<command id="KpiDateRangeScoreCommand" 			className="com.netsteadfast.greenstep.bsc.command.KpiDateRangeScoreCommand"/>
		<command id="ParentItemDateRangeScoreCommand"	className="com.netsteadfast.greenstep.bsc.command.ParentItemDateRangeScoreCommand"/>
		<command id="DashboardNewExcelCommand"				className="com.netsteadfast.greenstep.bsc.command.DashboardNewExcelCommand"/>
	</chain>

	<!-- KPIs Period Trends 輸出 Excel 產生用的 chain -->
	<chain name="kpiPeriodTrendsExcelCommandExcelContentChain">
		<command id="KpiPeriodTrendsExcelCommand"				className="com.netsteadfast.greenstep.bsc.command.KpiPeriodTrendsExcelCommand"/>
	</chain>

	<!-- PDCA報表HTML版產生內容用的 chain -->
	<chain name="pdcaReportHtmlContentChain">
		<command id="LoadPdcaDataCommand"			className="com.netsteadfast.greenstep.bsc.command.LoadPdcaDataCommand"/>
		<command id="PdcaReportBodyCommand"		className="com.netsteadfast.greenstep.bsc.command.PdcaReportBodyCommand"/>
	</chain>

	<!-- PDCA報表Excel版產生內容用的 chain -->
	<chain name="pdcaReportExcelContentChain">
		<command id="LoadPdcaDataCommand"			className="com.netsteadfast.greenstep.bsc.command.LoadPdcaDataCommand"/>
		<command id="PdcaReportExcelCommand"	className="com.netsteadfast.greenstep.bsc.command.PdcaReportExcelCommand"/>
	</chain>

	<!-- Forecast analysis 輸出 Excel 產生用的 chain -->
	<chain name="timeSeriesAnalysisExcelCommandContentChain">
		<command id="TimeSeriesAnalysisExcelCommand"				className="com.netsteadfast.greenstep.bsc.command.TimeSeriesAnalysisExcelCommand"/>
	</chain>

</catalog>


text:
This is an include that provides a more consistent and responsive damage system with many new features.

It's pretty much plug-and-play if you don't have any filterscripts that interfere with the health or death events.

# How to use

1. `#include <weapon-config>` before any other script
2. Replace `OnPlayerGiveDamage` and `OnPlayerTakeDamage` with just one callback:

    ```pawn
    public OnPlayerDamage(&playerid, &Float:amount, &issuerid, &weapon, &bodypart)
    ```
3. Add config functions in `OnGameModeInit` (or any other places, they can be called at any time).
    **Recommended**:

    ```pawn
    public OnGameModeInit() {
        SetVehiclePassengerDamage(true);
        SetDisableSyncBugs(true);
    }
    ```

## Requirements

This include file requires the [SKY](https://github.com/oscar-broman/SKY/) plugin.

# Features

- **Server-side health**
    - Impossible to use health hacks on lagcomp mode
    - Any type of damage can be modified/prevented, even falling 1000m from the sky
    - Vending machines are controlled server-side (buildings removed and objects created)
    - Paused players can be killed (with death animations) and their HP bars always show the correct values
- **Destroy vehicles with a passenger but no driver**
- **Custom falling damage (optional)**
    - Adjust the damage and at which speed a player will die
- **Sounds and on-screen TextDraw indicators of damage given/taken**
    - Also shows another player's damage feed when spectating
- **New weapon types detected**:
    - `WEAPON_PISTOLWHIP` - When you punch someone with a gun
    - `WEAPON_VEHICLE_M4` - Vehicles with M4 guns (e.g. Rustler)
    - `WEAPON_VEHICLE_MINIGUN` - Vehicles with miniguns (e.g. Hunter)
    - `WEAPON_HELIBLADES` - Helikill
    - `WEAPON_CARPARK` - When you park your car on someone
- **Extensive sanity checking on shots:**
    - Modified weapon.dat is automatically detected
    - Shot vector, player distance, and much more is examined
    - A callback is invoked for each so-called "rejected hit" so that the player is informed. A few of these are:
        - Inflicting damage when already dead (due to lag)
        - Hit a player too far from the shot hit position (due to severe lag or cheating)
        - Hitting/shooting too fast (due to severe lag or cheating)
- **Modify every weapon's damage amount**
    - To a single value
    - To multiple values depending on the shot distance
    - With custom logic in a callback, for example:
        - Increase damage for headshots
        - Increase/lower damage for combos
        - Lower damage for c-bug rapid fire
- **Knife sync fixed in both lagcomp and no-lagcomp**
- **New death atnimations and respawn logic**
    - Customize respawn time globally and for each death
    - Fully customizable animations, with a nice set of defaults
    - Different animation depending on weapon/bodypart, for example:
        - Headshots make you fall back with both hands in your face
        - Shotgun kills make you fly backward like in GTA:VC (unless killed from behind)

## Implementation details

All players are given infinite health and set to the same team. Damage is counted by the script whenever `OnPlayer(Give/Take)Damage` is called. The real `GetPlayerHealth` is **never** read by the include file.

The players healthbars are modified by editing SA-MP packets, so they are very responsive.

The death animations are applied as "forcesync" and even the facing angle is force synced (with SKY). This allows perfect animations even for laggy/paused players.

The *real* `OnPlayerDeath` is never called from the SA-MP server (only in some rare cases). A player never actually dies in their game - they just see a death animation applied and get respawned.

Many SA-MP functions are hooked to provide new values (such as `GetPlayerState`, `(Get/Set)Player(Health/Armour)`, `GetPlayerTeam`).

## Caveats

At the moment, filterscripts are not fully supported. If you need to modify the health, go into spec mode, change the virtual world, and more then you should do it through the gamemode.

A simple workaround is to just do something like this:

```pawn
// In the gamemode
forward SetHealth(playerid, Float:health);
public SetHealth(playerid, Float:health) {
    SetPlayerHealth(playerid, health);
}
// In the filterscript
CallRemoteFunction("SetHealth", "i", playerid, health);
```

# API

## Callbacks

### Existing callbacks

`OnPlayerGiveDamage` and `OnPlayerTakeDamage` are removed. Use `OnPlayerDamage` (see below).

`OnPlayerDeath` and `OnPlayerWeaponShot` are called as usual.

### New callbacks

```pawn
public OnPlayerDamage(playerid, &Float:amount, &issuerid, &weapon, &bodypart);
```
Called when damage is about to be inflicted on a player
Most arguments can be modified (e.g. the damage could be adjusted)
* `playerid` - The player who is about to get damaged
* `amount` - The amount of damage about to get inflicted (0.0 means all HP)
    This will not always be the same in OnPlayerDamageDone, for example:
    if amount is 50.0 and you have 10.0, only 10.0 will be reported in OnPlayerDamageDone
* `weapon` - The weapon used to inflict the damage
* `bodypart` - The bodypart

Return 0 to prevent the damage from being inflicted

```pawn
public OnPlayerDamageDone(playerid, Float:amount, issuerid, weapon, bodypart);
```
Called after damage has been inflicted

Same parameters as above, but they can not be modified

Return value ignored

```pawn
public OnPlayerPrepareDeath(playerid, animlib[32], animname[32], &anim_lock, &respawn_time);
```
Before the death animation is applied

* `playerid` - The player that is about to die
* `animlib` - The anim lib to play (change to empty string for no animation)
* `animname` - The anim name to play
* `anim_lock` - The "lock" parameter in ApplyAnimation
* `respawn_time` - The time (in milliseconds) until the player respawns

Return value ignored

```pawn
public OnPlayerDeathFinished(playerid);
```
When the death animation has finished and the player has been sent to respawn

* `playerid` - The player

Return value ignored

```pawn
public OnRejectedHit(playerid, hit[E_REJECTED_HIT]);
```
When a shot or damage given is rejected
See E_REJECTED_HIT and GetRejectedHit for more

* `playerid` - The player whose hit was rejected
* `hit` - An enum containing information about the rejected hit

Return value ignored

```pawn
public OnInvalidWeaponDamage(playerid, damagedid, Float:amount, weaponid, bodypart, error, bool:given);
```
When a player takes or gives invalid damage (WC_* errors above)
* `playerid` - The player that inflicted the damage
* `damagedid` - The player that took or was given a hit
* `amount` - The damage amount inflicted
* `weaponid` - The weapon used
* `bodypart` - The bodypart
* `error` - Which error (see the enum containing WC_NO_ERROR)
* `given` - `true` means that `playerid` reported the damage in `OnPlayerGiveDamage`,
    `false` means that `damagedid` reported the damage in `OnPlayerTakeDamage`

Return value ignored

## Functions

```pawn
AverageShootRate(playerid, shots, &multiple_weapons = 0);
```
The average time (in milliseconds) between shots.
* `playerid` - The player
* `hits` - Number of hits to average on (max 10)
* `multiple_weapons` - Will be set to 1 if different weapons were used in the last shots

Returns -1 if there is not enough data to calculate the rate, otherwise the average time is returned.

```pawn
AverageHitRate(playerid, hits, &multiple_weapons = 0);
```
Same as above, but for hits inflicted with `OnPlayerGiveDamage`

```pawn
DamagePlayer(playerid, Float:amount, issuerid = INVALID_PLAYER_ID, weaponid = WEAPON_UNKNOWN, bodypart = BODY_PART_UNKNOWN);
```
Inflict a hit on a player. All callbacks except `OnPlayerWeaponShot` will be called.

```pawn
Float:GetPlayerHealth(playerid, &Float:health = 0.0);
```
Hooked version of the original, which also returns the value

```pawn
Float:GetPlayerArmour(playerid, &Float:armour = 0.0);
```
Hooked version of the original, which also returns the value

```pawn
GetRejectedHit(playerid, idx, output[], maxlength = sizeof(output));
```
Get a string explaining why the hit was rejected at idx (max. `WC_MAX_REJECTED_HITS - 1`)

```pawn
SetRespawnTime(ms);
```
Set the respawn time in milliseconds

```pawn
GetRespawnTime();
```
Get the respawn time

```pawn
IsBulletWeapon(weaponid);
```
Returns true if the weapon shoots bullets

```pawn
IsHighRateWeapon(weaponid);
```
Returns true if the weapon's damage can be reported in high rates to the server (such as fire)

```pawn
IsMeleeWeapon(weaponid);
```
Returns true if it's a melee weapon (including `WEAPON_PISTOLWHIP`)

```pawn
IsPlayerDying(playerid);
```
Returns true if the player is between the dying animation and spawning

```pawn
IsPlayerSpawned(playerid);
```
Returns true if the player is spawned and not in a dying animation

```pawn
GetWeaponName(weaponid, weapon[], len = sizeof(weapon));
```
Hooked version of the native, fixed and containing custom weapons (such as pistol whip)

```pawn
ReturnWeaponName(weaponid);
```
Return the weapon name (uses the fixed GetWeaponName)

```pawn
SetCustomFallDamage(bool:toggle, Float:damage_multiplier = 25.0, Float:death_velocity = -0.6);
```
Toggle custom falling damage

```pawn
SetCustomFallDamageMachines(bool:toggle);
```
Toggle vending machines (they are removed and disabled by default)

```pawn
SetDamageFeed(bool:toggle);
```
Toggle damage feed

```pawn
SetDamageSounds(taken, given);
```
Set sounds when damage is given and taken (0 to disable)

```pawn
SetVehiclePassengerDamage(bool:toggle);
```
Allow vehicles to be damaged when they have a passenger and no driver

```pawn
SetVehicleUnoccupiedDamage(bool:toggle);
```
Allow vehicles to be damaged when they don't have any players inside them

```pawn
SetWeaponDamage(weaponid, damage_type, Float:amount, Float:...);
```
Modify a weapon's damage
* `weaponid` - The weapon to modify
* `damage_type` - One of the following:
    * DAMAGE_TYPE_MULTIPLIER
        Multiply the original damage inflicted by amount
        This is default for melee, grenades, and other weapons that
        inflict different amounts of damage (shotguns excluded)
    * DAMAGE_TYPE_STATIC
        Inflict a specific amount of damage for each hit
        For shotguns, this modifies the value for each bullet that hit the player
        Combat shotgun shoots 8 bullets, other shotguns shoot 15
    * DAMAGE_TYPE_RANGE_MULTIPLIER
        Same as DAMAGE_TYPE_MULTIPLIER, but the damage depends on the distance
    * DAMAGE_TYPE_RANGE
        Same as DAMAGE_TYPE_STATIC, but the damage depends on the distance
* `amount` - The amount of damage
* `...` - If `damage_type` contains `RANGE`, the arguments should be a list of ranges and damage
    For example:
    ```pawn
    SetWeaponDamage(WEAPON_SNIPER, WEAPON_TYPE_RANGE, 40.0, 20.0, 30.0, 60.0, 20.0)
    ```
    This will make sniper damage:
    * `40` if distance is less than `20`
    * `30` if distance is less than `60`
    * `20` for any other distance

```pawn
SetWeaponMaxRange(weaponid, Float:range);
```
Set the max range of a weapon. The default value is those from weapon.dat
Because of a SA-MP bug, weapons can (and will) exceed this range.
This script, however, will block those out-of-range shots and give a rejected hit.

```pawn
SetWeaponShootRate(weaponid, max_rate);
```
Set the max allowed shoot rate of a weapon.
Could be used to prevent C-bug damage or allow infinite shooting if a script uses GivePlayerWeapon to do so.


text:
using cg::data::Glsl_program_desc;
using cg::rnd::opengl::set_uniform;
using cg::rnd::opengl::set_uniform_array_int;
using cg::rnd::opengl::set_uniform_array_float;
using cg::rnd::opengl::set_uniform_array_float3;
using cg::rnd::opengl::set_uniform_array_mat3;
using cg::rnd::opengl::set_uniform_array_mat4;

namespace deferred_lighting {

// ----- Gbuffer_pass_shader_program -----

Gbuffer_pass_shader_program::Gbuffer_pass_shader_program(const Glsl_program_desc& source_code) :
	_prog(source_code),
	_u_projection_matrix_location(uniform_location(_prog, "u_projection_matrix")),
	_u_view_matrix_location(uniform_location(_prog, "u_view_matrix")),
	_u_arr_model_matrix_location(uniform_location(_prog, "u_arr_model_matrix")),
	_u_arr_smoothness_location(uniform_location(_prog, "u_arr_smoothness")),
	_u_arr_tex_normal_map_location(uniform_location(_prog, "u_arr_tex_normal_map"))
{}

void Gbuffer_pass_shader_program::set_uniform_array_model_matrix(const float* ptr, GLsizei count) noexcept
{
	set_uniform_array_mat4(_u_arr_model_matrix_location, ptr, count);
}

void Gbuffer_pass_shader_program::set_uniform_array_smoothness(const float* ptr, GLsizei count) noexcept
{
	set_uniform_array_float(_u_arr_smoothness_location, ptr, count);
}

void Gbuffer_pass_shader_program::use(const float4x4& projection_matrix, const float4x4& view_matrix) noexcept
{
	glUseProgram(_prog.id());
	set_uniform(_u_projection_matrix_location, projection_matrix);
	set_uniform(_u_view_matrix_location, view_matrix);
}

// ----- Lighting_pass_dir_shader_program -----

Lighting_pass_dir_shader_program::Lighting_pass_dir_shader_program(
	const Glsl_program_desc& dir_source_code) :
	_prog(dir_source_code),
	_u_arr_far_pane_coords_location(uniform_location(_prog, "u_arr_far_plane_coords")),
	_u_dlight_direction_to_light_vs_location(uniform_location(_prog, "u_dlight.direction_to_light_vs")),
	_u_dlight_irradiance_location(uniform_location(_prog, "u_dlight.irradiance")),
	_u_dlight_ambient_irradiance_up_location(uniform_location(_prog, "u_dlight.ambient_irradiance_up")),
	_u_dlight_ambient_irradiance_down_location(uniform_location(_prog, "u_dlight.ambient_irradiance_down"))
{}

void Lighting_pass_dir_shader_program::set_uniform_array_far_plane_coords(
	const std::array<float3, 4>& far_plane_coords) noexcept
{
	float arr[12] = {
		far_plane_coords[0].x, far_plane_coords[0].y, far_plane_coords[0].z,
		far_plane_coords[1].x, far_plane_coords[1].y, far_plane_coords[1].z,
		far_plane_coords[2].x, far_plane_coords[2].y, far_plane_coords[2].z,
		far_plane_coords[3].x, far_plane_coords[3].y, far_plane_coords[3].z,
	};

	set_uniform_array_float3(_u_arr_far_pane_coords_location, arr, GLsizei(far_plane_coords.size()));
}

void Lighting_pass_dir_shader_program::use(const Directional_light_params& dl_params) noexcept
{
	glUseProgram(_prog.id());
	set_uniform(_u_dlight_direction_to_light_vs_location, -dl_params.direction_vs);
	set_uniform(_u_dlight_irradiance_location, dl_params.irradiance);
	set_uniform(_u_dlight_ambient_irradiance_up_location, dl_params.ambient_irradiance_up);
	set_uniform(_u_dlight_ambient_irradiance_down_location, dl_params.ambient_irradiance_down);
}

// ----- Material_lighting_pass -----

Material_lighting_pass_shader_program::Material_lighting_pass_shader_program(const Glsl_program_desc& source_code) :
	_prog(source_code),
	_u_projection_matrix_location(uniform_location(_prog, "u_projection_matrix")),
	_u_view_matrix_location(uniform_location(_prog, "u_view_matrix")),
	_u_dir_light_projection_matrix_location(uniform_location(_prog, "u_dir_light_projection_matrix")),
	_u_dir_light_view_matrix_location(uniform_location(_prog, "u_dir_light_view_matrix")),
	_u_arr_model_matrix_location(uniform_location(_prog, "u_arr_model_matrix")),
	_u_arr_tex_diffuse_rgb_location(uniform_location(_prog, "u_arr_tex_diffuse_rgb")),
	_u_arr_tex_specular_intensity_location(uniform_location(_prog, "u_arr_tex_specular_intensity"))
{}

void Material_lighting_pass_shader_program::set_uniform_array_model_matrix(const float* ptr, size_t count) noexcept
{
	set_uniform_array_mat4(_u_arr_model_matrix_location, ptr, GLsizei(count));
}

void Material_lighting_pass_shader_program::use(const float4x4& projection_matrix, const float4x4& view_matrix,
	const Directional_light_params& dir_light) noexcept
{
	glUseProgram(_prog.id());
	set_uniform(_u_projection_matrix_location, projection_matrix);
	set_uniform(_u_view_matrix_location, view_matrix);
	set_uniform(_u_dir_light_projection_matrix_location, dir_light.projection_matrix);
	set_uniform(_u_dir_light_view_matrix_location, dir_light.view_matrix);
}

// ----- Shadow_map_pass_shader_program -----

Shadow_map_pass_shader_program::Shadow_map_pass_shader_program(const Glsl_program_desc& source_code) :
	_prog(source_code),
	_u_projection_matrix_location(uniform_location(_prog, "u_projection_matrix")),
	_u_view_matrix_location(uniform_location(_prog, "u_view_matrix")),
	_u_arr_model_matrix_location(uniform_location(_prog, "u_arr_model_matrix"))
{}

void Shadow_map_pass_shader_program::set_uniform_array_model_matrix(const float* ptr, size_t count) noexcept
{
	set_uniform_array_mat4(_u_arr_model_matrix_location, ptr, GLsizei(count));
}

void Shadow_map_pass_shader_program::use(const Directional_light_params& dir_light) noexcept
{
	glUseProgram(_prog.id());
	set_uniform(_u_projection_matrix_location, dir_light.projection_matrix);
	set_uniform(_u_view_matrix_location, dir_light.view_matrix);
}

// ----- Ssao_pass_shader_program -----

Ssao_pass_shader_program::Ssao_pass_shader_program(const Glsl_program_desc& source_code) :
	_prog(source_code),
	_u_arr_sample_ray_location(uniform_location(_prog, "u_arr_sample_ray")),
	_u_arr_random_normal_location(uniform_location(_prog, "u_arr_random_normal"))//,
{}

void Ssao_pass_shader_program::use(const std::vector<float3>& sample_rays_and_normals,
	size_t sample_ray_count, size_t random_normal_count) noexcept
{
	glUseProgram(_prog.id());

	set_uniform_array_float3(_u_arr_sample_ray_location,
		reinterpret_cast<const float*>(sample_rays_and_normals.data()), GLsizei(sample_ray_count));

	set_uniform_array_float3(_u_arr_random_normal_location,
		reinterpret_cast<const float*>(sample_rays_and_normals.data() + sample_ray_count), GLsizei(random_normal_count));
}

// ----- Tone_mapping_pass_shader_program -----

Tone_mapping_pass_shader_program::Tone_mapping_pass_shader_program(const cg::data::Glsl_program_desc& source_code) :
	_prog(source_code)
{}

void Tone_mapping_pass_shader_program::use() noexcept
{
	glUseProgram(_prog.id());
}

} // namespace deferred_lighting


text:
promise_test(async t => {
  let uuid = token();
  await fetchTest(t, {
    source: { server: Server.HTTPS_PRIVATE },
    target: {
      server: Server.HTTPS_LOCAL,
      behavior: {
        preflight: PreflightBehavior.singlePreflight(uuid),
        response: ResponseBehavior.allowCrossOrigin(),
      },
    },
    expected: FetchTestResult.SUCCESS,
  });
  await fetchTest(t, {
    source: { server: Server.HTTPS_PRIVATE },
    target: {
      server: Server.HTTPS_LOCAL,
      behavior: {
        preflight: PreflightBehavior.singlePreflight(uuid),
        response: ResponseBehavior.allowCrossOrigin(),
      },
    },
    expected: FetchTestResult.SUCCESS,
  });
}, "private to local: success.");

promise_test(async t => {
  let uuid = token();
  await fetchTest(t, {
    source: { server: Server.HTTPS_PUBLIC },
    target: {
      server: Server.HTTPS_LOCAL,
      behavior: {
        preflight: PreflightBehavior.singlePreflight(uuid),
        response: ResponseBehavior.allowCrossOrigin(),
      },
    },
    expected: FetchTestResult.SUCCESS,
  });
  await fetchTest(t, {
    source: { server: Server.HTTPS_PUBLIC },
    target: {
      server: Server.HTTPS_LOCAL,
      behavior: {
        preflight: PreflightBehavior.singlePreflight(uuid),
        response: ResponseBehavior.allowCrossOrigin(),
      },
    },
    expected: FetchTestResult.SUCCESS,
  });
}, "public to local: success.");

promise_test(async t => {
  let uuid = token();
  await fetchTest(t, {
    source: { server: Server.HTTPS_PUBLIC },
    target: {
      server: Server.HTTPS_PRIVATE,
      behavior: {
        preflight: PreflightBehavior.singlePreflight(uuid),
        response: ResponseBehavior.allowCrossOrigin(),
      },
    },
    expected: FetchTestResult.SUCCESS,
  });
  await fetchTest(t, {
    source: { server: Server.HTTPS_PUBLIC },
    target: {
      server: Server.HTTPS_PRIVATE,
      behavior: {
        preflight: PreflightBehavior.singlePreflight(uuid),
        response: ResponseBehavior.allowCrossOrigin(),
      },
    },
    expected: FetchTestResult.SUCCESS,
  });
}, "public to private: success.");


text:
//-- Legacy OpenGL
/*
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

using namespace std;

int main(void)
{
    GLFWwindow* window;

    // Initialize the library
    if(!glfwInit()) {
        return -1;
    }

    // Create a windowed mode window and its OpenGL context
    window = glfwCreateWindow(640, 480, "Legacy OpenGL", NULL, NULL);
    if(!window) {
        // GLFW window creation failed!
        glfwTerminate();
        return -1;
    }

    // Make the window context current
    glfwMakeContextCurrent(window);

    if(glewInit() != GLEW_OK) {
        cout << "Error!" << endl;
    }

    // Loop until the user closes the window
    while(!glfwWindowShouldClose(window)) {

        // Render here
        glClear(GL_COLOR_BUFFER_BIT);

        glBegin(GL_TRIANGLES);
        glVertex2f(-0.5f, -0.5f);
        glVertex2f(0.0f, 0.5f);
        glVertex2f(0.5f, -0.5f);
        glEnd();

        // Swap front and back buffers
        glfwSwapBuffers(window);

        // Poll for and process events
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
*/

//-- Modern OpenGL
// We want to transform legacy to modern OpenGL

//-- Foundation of Modern OpenGL
// Vertex buffer is the data to draw triangle and shader execute and draw that triangle on the gpu.
// Vertex Buffer - Is an array of memory, or a simple buffer. Is a array of memory to place binary in there.
// Shader - Is a program on the gpu, is code that only run on the gpu.
// OpenGL behave as State Machine

//-- Init Moderns OpenGL
/*
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

using namespace std;

int main(void)
{
    GLFWwindow* window;

    // Initialize the library
    if(!glfwInit()) {
        return -1;
    }

    // Create a windowed mode window and its OpenGL context
    window = glfwCreateWindow(640, 480, "Moderns OpenGL", NULL, NULL);
    if(!window) {
        // GLFW window creation failed!
        glfwTerminate();
        return -1;
    }

    // Make the window context current
    glfwMakeContextCurrent(window);

    if(glewInit() != GLEW_OK) {
        cout << "Error!" << endl;
    }

    // Define ours buffer
    // Generate a buffer and return back his ID, to OpenGL identify that buffer and used.
    unsigned int buffer;
    glGenBuffers(1, &buffer);

    // Select that buffer, first param, porpuse of using and second param buffer
    glBindBuffer(GL_ARRAY_BUFFER, buffer);

    // Define the data of the buffer, first params, type of that data, second param how big
    float positions[6] = {
        -0.5f, -0.5f,
         0.0f,  0.5f,
         0.5f, -0.5f
    };

    glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);

    // Loop until the user closes the window
    while(!glfwWindowShouldClose(window)) {

        // Render here
        glClear(GL_COLOR_BUFFER_BIT);

        // We need shader to display triangle, otherwise, will display none.
        glDrawArrays(GL_TRIANGLES, 0, 3);

        // Swap front and back buffers
        glfwSwapBuffers(window);

        // Poll for and process events
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
*/

//-- Vertex attributes
// If for define the layouts of ours vertices. Vertex is just a point.
/*
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

using namespace std;

int main(void)
{
    GLFWwindow* window;

    if(!glfwInit()) {
        return -1;
    }

    window = glfwCreateWindow(640, 480, "Moderns OpenGL", NULL, NULL);
    if(!window) {
        // GLFW window creation failed!
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    if(glewInit() != GLEW_OK) {
        cout << "Error!" << endl;
    }

    float positions[6] = {
        -0.5f, -0.5f,
         0.0f,  0.5f,
         0.5f, -0.5f
    };

    unsigned int buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);

    // Vertex attributes
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

    while(!glfwWindowShouldClose(window)) {

        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        glfwSwapBuffers(window);

        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}
*/
//-- Adding shaders
// vertex and fragment shader type are 90% more used shader on graphics.
// vertex shader, pourpose is to tell gpu where position on the screen we want to render specific each vertex. If we have three vertex, we call this 3 time.
// fragment or pixel shader, determine where to fill pixel inside of the figure we create and color.
#include <iostream>
#include <GL/glew.h>
#include <GLFW/glfw3.h>

using namespace std;

// Function to compile shaders
static unsigned int CompileShader(unsigned int type, const string &source) {
    unsigned int id = glCreateShader(type);
    const char* src = source.c_str();
    glShaderSource(id, 1, &src, nullptr);
    glCompileShader(id);

    // Error handling
    int result;
    glGetShaderiv(id, GL_COMPILE_STATUS, &result);
    if(result == GL_FALSE) {
        int length;
        glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
        char* message = (char*) alloca(length * sizeof(char));
        glGetShaderInfoLog(id, length, &length, message);
        cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << "shader!" << endl;
        cout << message << endl;
        glDeleteShader(id);
        return 0;
    }

    return id;
}

static unsigned int CreateShader(const string &vertexShader, const string &fragmentShader) {
    // Initialize program
    unsigned int program = glCreateProgram();

    // Shader objects or files
    unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
    unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);

    // Attach to the program
    glAttachShader(program, vs);
    glAttachShader(program, fs);
    glLinkProgram(program);
    glValidateProgram(program);

    glDeleteShader(vs);
    glDeleteShader(fs);

    return program;
}

int main(void)
{
    GLFWwindow* window;

    if(!glfwInit()) {
        return -1;
    }

    window = glfwCreateWindow(640, 480, "Moderns OpenGL", NULL, NULL);
    if(!window) {
        // GLFW window creation failed!
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    if(glewInit() != GLEW_OK) {
        cout << "Error!" << endl;
    }

    float positions[6] = {
        -0.5f, -0.5f,
         0.0f,  0.5f,
         0.5f, -0.5f
    };

    unsigned int buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);

    // Vertex attributes
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);

    // Writing shader
    string vertexShader =
        // Version of GLSL
        "#version 330 core \n"
        "\n"
        "layout(location = 0) in vec4 position;"
        "\n"
        "void main()\n"
        "{\n"
        "gl_Position = position; \n"
        "} \n";

    string fragmentShader =
        // Version of GLSL
        "#version 330 core \n"
        "\n"
        "layout(location = 0) out vec4 color;"
        "\n"
        "void main()\n"
        "{\n"
        "color = vec4(1.0, 0.0, 0.0, 1.0); \n"
        "} \n";

    unsigned int shader = CreateShader(vertexShader, fragmentShader);
    glUseProgram(shader);

    while(!glfwWindowShouldClose(window)) {

        glClear(GL_COLOR_BUFFER_BIT);

        glDrawArrays(GL_TRIANGLES, 0, 3);

        glfwSwapBuffers(window);

        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

// If you dont provide shader, some GPU provide Shader for you on default. That why some GPU render the triangule without shader.

// Compile command pront
// g++ main.cpp -o main -std=c++11 -lGL -lglfw -lGLEW

// In case of this error:
// error: GLSL 3.00 is not supported. Supported versions are: 1.10, 1.20, 1.30, 1.00 ES, and 3.00 ES

// You can check you GLSL version by type this on cmd:
// glxinfo | grep OpenGL

// Then adjust you Shade code version to you machine compatability or support language.


text:
package eu.ehealth.controllers;

import java.rmi.RemoteException;
import java.util.Date;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.Session;
import org.zkoss.zk.ui.Sessions;
import org.zkoss.zk.ui.SuspendNotAllowedException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zul.Button;
import org.zkoss.zul.Hbox;
import org.zkoss.zul.Label;
import org.zkoss.zul.Separator;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.Window;
import eu.ehealth.ErrorDictionary;
import eu.ehealth.SystemDictionary;
import eu.ehealth.controllers.details.ChangePassword;
import eu.ehealth.controllers.details.assessment.CarerAssessmentInfo;
import eu.ehealth.controllers.details.assessment.CarerAssessmentPopupController;
import eu.ehealth.ws_client.StorageComponentImpl;
import eu.ehealth.ws_client.xsd.Carer;
import eu.ehealth.ws_client.xsd.CarerAssessment;
import eu.ehealth.ws_client.xsd.OperationResult;
import eu.ehealth.ws_client.xsd.PersonData;
import eu.ehealth.ws_client.xsd.SocioDemographicData;
import eu.ehealth.ws_client.xsd.User;

/**
 * Public class built to manage Carer forms to create and update carrer objects
 *
 * @author Xavi Sarda (Atos Origin)
 */
public class CarerControllerWindow extends SDFormControllerWindow
{

	private static final long serialVersionUID = 7241911276370717234L;
	private CarerAssessmentPopupController assessmentWindow;

	/**
	 * Default constructor (for new Carer)
	 */
	public CarerControllerWindow()
	{
		isNewUser = true;
		this.buildForm(true);
	}

	/**
	 * Constructor for updating a Carer
	 *
	 * @param current Carer object to be updated
	 * @param details Boolean flag to let the called methods that they must be shown in a proper way to update carers objects
	 */
	public CarerControllerWindow(Carer current, boolean details)
	{
		isNewUser = false;

		this.currentid = current.getID();
		this.currentdata = current.getPersonData();
		this.currentsd = current.getSDData();
		this.detailsmode = details;
		this.buildForm(false);

		this.addPersonFieldsValues();
		this.addAddressFieldsValues();
		this.addCommunicationFieldsValues();
		this.addBirthdayFieldValue(this.currentsd.getBirthdayDate());
		Hbox buttonshbox = new Hbox();
		if (this.detailsmode)
		{
			buttonshbox.appendChild(this.createEditButton());
		}
		else
		{
			buttonshbox.appendChild(this.createUpdateButton());
		}
		Separator sep = new Separator();
		sep.setWidth("10px");
		sep.setOrient("horizontal");
		buttonshbox.appendChild(sep);
		buttonshbox.appendChild(this.createPasswordButton());
		this.appendChild(buttonshbox);
		this.getFellow("pat_uname").getParent().setVisible(false);
	}

	/**
	 * Build form instructions to be executed
	 */
	public void buildForm(boolean newCarer)
	{
		this.addErrorBox();
		this.addPersonFields(newCarer);
		this.addAddressFields();
		this.addCommunicationFields();
		this.addBirthdayField();
	}

	/**
	 * Submit function: Used on the view layer to create a new Patient (using
	 * the StorageComponentImpl).
	 *
	 * @return void but saves a new Patient on the StorageComponent
	 */
	public void createCarer()
	{
		if (!validateForm())
		{
			return;
		}

		Date birthd = ((Datebox) this.getFellow("pat_age")).getValue();

		// Getting information from form fields
		PersonData personData = this.getPersonData();
		// SocioDemographicData sdData = this.getSocioDemographicData();
		SocioDemographicData sdData = new SocioDemographicData();

		sdData.setBirthdayDate(birthd);
		// TODO isPrimary control on Communication and Addresses
		Carer carer = new Carer("", personData, sdData);
		try
		{
			StorageComponentImpl proxy = new StorageComponentImpl();
			Session ses = Sessions.getCurrent();
			String id = (String) ses.getAttribute("userid");
			OperationResult result = proxy.createCarer(carer, id);
			String username = this.getUsername();

			User user = createNewUser(SystemDictionary.USERTYPE_CARER, result.getCode(), username);
			result = proxy.createUser(user);
			if (!result.getDescription().equals("ok"))
			{
				SystemDictionary.webguiLog("TRACE", "Error creating user");
				Window win = (Window) getFellow("internalformerror");
				((Label) win.getFellow("errorlbl")).setValue("Username not valid");
				getFellow("internalformerror").setVisible(true);
				SystemDictionary.webguiLog("TRACE", "Deleting Carer...");
				OperationResult newresult = proxy.deleteCarer(user.getPersonID(), id);
				SystemDictionary.webguiLog("TRACE", "Delete Carer result: " + newresult.getCode());
				return;
			}
			Executions.getCurrent().sendRedirect("/carers/index.zul");
		}
		catch (Exception e)
		{
			ErrorDictionary.redirectWithError("/carers/?error="
					+ ErrorDictionary.UNKOW_ERROR);
		}
	}

	/**
	 * Submit function: Used on the view layer to update an existing Patient
	 * using the StorageComponentImpl appropriate call.
	 *
	 * @return void but saves a new Patient on the StorageComponent
	 */
	public void updateCarer()
	{
		// Getting information from form fields
		PersonData personData = this.getPersonData();
		// SocioDemographicData sdData = this.getSocioDemographicData();
		SocioDemographicData sdData = new SocioDemographicData();
		sdData.setBirthdayDate(((Datebox) this.getFellow("pat_age")).getValue());
		// TODO isPrimary control on Communication and Addresses
		Carer carer = new Carer(this.currentid, personData, sdData);
		try
		{
			StorageComponentImpl proxy = new StorageComponentImpl();
			Session ses = Sessions.getCurrent();
			String id = (String) ses.getAttribute("userid");
			proxy.updateCarer(carer, id);
		}
		catch (Exception e)
		{
			ErrorDictionary.redirectWithError("/carers/?error="
					+ ErrorDictionary.UNKOW_ERROR);
		}
		finally
		{
			// TODO Show message on the following page.
			Executions.getCurrent().sendRedirect("/carers/index.zul");
		}
	}

	/**
	 * This method creates a button to update carers using the existing form
	 *
	 * @return Button object to be added to the form
	 */
	public Button createUpdateButton()
	{
		Button btn = new Button();
		String text = Labels.getLabel("carers.update.title");
		btn.setLabel(text);
		btn.addEventListener("onClick", new EventListener() {
			public void onEvent(Event arg0) throws Exception
			{
				updateCarer();
			}
		});

		return btn;
	}

	/**
	 * This method creates a button to allow modification to the current carer
	 * using this form
	 *
	 * @return Button object to be added to the form
	 */
	public Button createEditButton()
	{
		Button btn = new Button();
		String text = Labels.getLabel("carers.edit");
		btn.setLabel(text);
		btn.addEventListener("onClick", new EventListener() {
			public void onEvent(Event arg0) throws Exception
			{
				Executions.getCurrent().sendRedirect("/carers/update.zul?carerid=" + currentid);
			}
		});
		return btn;
	}

	/**
	 *
	 * @return
	 */
	public Button createPasswordButton()
	{
		Button btn = new Button("Change Password");
		btn.addEventListener("onClick", new EventListener() {
			public void onEvent(Event arg0) throws Exception
			{
				createPasswordDialog();
			}
		});
		return btn;
	}

	/**
	 *
	 * @throws SuspendNotAllowedException
	 * @throws InterruptedException
	 * @throws RemoteException
	 */
	public void createPasswordDialog() throws SuspendNotAllowedException, InterruptedException, RemoteException
	{
		ChangePassword win = (ChangePassword) Executions.createComponents("password.zul", this, null);

		this.appendChild(win);
		StorageComponentImpl proxy = SystemDictionary.getSCProxy();
		String userid = (String) Sessions.getCurrent().getAttribute("userid");
		OperationResult ores = proxy.getUserIdByPersonId(this.currentid, SystemDictionary.USERTYPE_CARER_INT, userid);
		win.setuserid(ores.getCode());
		win.doModal();
	}

	/**
	 *
	 * @param assid
	 * @param carerid
	 */
	public void viewAssessmentDetail(String assid, String carerid)
	{
		StorageComponentImpl proxy = SystemDictionary.getSCProxy();
		CarerAssessment assessment = null;
		String userid = (String) Sessions.getCurrent().getAttribute("userid");
		try
		{
			CarerAssessment[] info = proxy.getCarerAssessmentsArr(carerid, userid);
			for (int i = 0; i < info.length; i++)
			{
				if (info[i].getID().equals(assid))
				{
					assessment = info[i];
				}
			}
			if (assessment == null)
			{
				throw new Exception("Assessment not found");
			}
			assessmentWindow = (CarerAssessmentPopupController) Executions.createComponents("assessmentcar.zul", this, null);
			this.setAssessmentValues(assessmentWindow, assessment);
			assessmentWindow.setVisible(true);
			assessmentWindow.doModal();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	/**
	 *
	 * @throws SuspendNotAllowedException
	 * @throws InterruptedException
	 */
	public void createAssessment() throws SuspendNotAllowedException, InterruptedException
	{
		assessmentWindow = (CarerAssessmentPopupController) Executions.createComponents("assessmentcar.zul", this, null);
		this.turnAssessment2Form(assessmentWindow);
		assessmentWindow.setVisible(true);
		assessmentWindow.doModal();
	}

	/**
	 *
	 * @param assessmentWindow
	 */
	protected void turnAssessment2Form(CarerAssessmentPopupController assessmentWindow)
	{
		for (int i = 0; i <= 4; i++)
		{
			if (i < 10)
			{
				assessmentWindow.getFellow("field0" + i).setVisible(false);
				assessmentWindow.getFellow("field0" + i + "_in").setVisible(true);
			}
		}
		assessmentWindow.getFellow("buttonrow").setVisible(true);
		assessmentWindow.getFellow("noformrow").setVisible(false);
		assessmentWindow.getFellow("datelabel").setVisible(false);
		((Textbox) assessmentWindow.getFellow("carerid")).setValue(this.currentid);
	}

	/**
	 *
	 * @param assessmentWindow
	 * @param assessment
	 */
	protected void setAssessmentValues(CarerAssessmentPopupController assessmentWindow, CarerAssessment assessment)
	{
		CarerAssessmentInfo cassessment = new CarerAssessmentInfo(assessment);
		((Label) assessmentWindow.getFellow("field0")).setValue(cassessment.getID());
		((Label) assessmentWindow.getFellow("field1")).setValue(cassessment.getCarerID());
		((Label) assessmentWindow.getFellow("field00")).setValue(cassessment.getRelevantHealthProblem());
		((Label) assessmentWindow.getFellow("field01")).setValue(cassessment.getSeverityOfBurden().toString());
		((Label) assessmentWindow.getFellow("field02")).setValue(cassessment.getEmotionalOrMentalDisorders());
		((Label) assessmentWindow.getFellow("field03")).setValue(cassessment.getPsychoactiveDrugs());
		((Label) assessmentWindow.getFellow("field04")).setValue(cassessment.getQualityOfLife().toString());
		((Label) assessmentWindow.getFellow("field05")).setValue(cassessment.getDateOfAssessment());
	}

	/**
	 *
	 * @param d
	 */
	public void addBirthdayFieldValue(Date d)
	{
		((Datebox) this.getFellow("pat_age")).setValue(d);
	}

	/**
	 *
	 * @return
	 */
	private boolean validateForm() {
		try {
			// check common fields
			if (!validateFormCommonFields())
				return false;

			return true;
		}
		catch (Exception e) {
			SystemDictionary.webguiLog("ERROR", e.getMessage());
			return false;
		}
	}

}


text:
package org.apache.wicket.markup.html;

import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupElement;
import org.apache.wicket.markup.MarkupStream;
import org.apache.wicket.markup.WicketTag;
import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
import org.apache.wicket.markup.resolver.ComponentResolvers;
import org.apache.wicket.markup.resolver.IComponentResolver;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.request.http.WebRequest;

/**
 * A simple "transparent" markup container.
 *
 * @author Juergen Donnerstag
 */
public class TransparentWebMarkupContainer extends WebMarkupContainer implements IComponentResolver
{
	private static final long serialVersionUID = 1L;

	/**
	 * Construct.
	 *
	 * @param id
	 *          The component id
	 */
	public TransparentWebMarkupContainer(String id)
	{
		super(id);
	}

	/**
	 * @see org.apache.wicket.markup.resolver.IComponentResolver#resolve(org.apache.wicket.MarkupContainer,
	 *      org.apache.wicket.markup.MarkupStream, org.apache.wicket.markup.ComponentTag)
	 */
	@Override
	public Component resolve(MarkupContainer container, MarkupStream markupStream, ComponentTag tag)
	{
		if (tag instanceof WicketTag && ((WicketTag)tag).isFragmentTag())
		{
			// even having a wicket:id it isn't a component's markup
			return null;
		}

		Component resolvedComponent = getParent().get(tag.getId());
		if (resolvedComponent != null && getPage().wasRendered(resolvedComponent))
		{
			/*
			 * Means that parent container has an associated homonymous tag to this grandchildren
			 * tag in markup. The parent container wants render it and it should be not resolved to
			 * their grandchildren.
			 */
			return null;
		}
		return resolvedComponent;
	}

	@Override
	public void internalRenderHead(HtmlHeaderContainer container)
	{
		/*
		 * https://issues.apache.org/jira/browse/WICKET-5941
		 *
		 * if this component is updated via AJAX and is the root
		 * one, then render head also for embedded components.
		 */
		if (isAjaxRequest() && !isParentRendering())
		{
			renderHeadForInnerSiblings(container);
		}

		super.internalRenderHead(container);
	}

	/**
	 * Says if parent container is rendering or not.
	 *
	 * @return true if parent is rendering, false otherwise.
	 */
	private boolean isParentRendering()
	{
		MarkupContainer parent = getParent();

		return parent != null && parent.isRendering();
	}

	/**
	 * Says if the current request is an AJAX one.
	 *
	 * @return true if the current request is an AJAX one, false otherwise.
	 */
	private boolean isAjaxRequest()
	{
		Request request = RequestCycle.get().getRequest();

		if (request instanceof WebRequest)
		{
			WebRequest webRequest = (WebRequest)request;
			return webRequest.isAjax();
		}

		return false;
	}

	/**
	 * Renders head for embedded component, i.e. those who are not added
	 * directly to this container but have the markup inside it.
	 *
	 * @param container
	 * 				The HtmlHeaderContainer
	 */
	private void renderHeadForInnerSiblings(HtmlHeaderContainer container)
	{
		MarkupStream stream = new MarkupStream(getMarkup());

		while (stream.isCurrentIndexInsideTheStream())
		{
			MarkupElement childOpenTag = stream.nextOpenTag();

			if ((childOpenTag instanceof ComponentTag) && !stream.atCloseTag())
			{
				// Get element as tag
				final ComponentTag tag = (ComponentTag)childOpenTag;

				// Get component id
				final String id = tag.getId();

				Component component = null;

				if (get(id) == null)
				{
					component = ComponentResolvers.resolveByComponentHierarchy(this, stream, tag);
				}

				if (component != null)
				{
					component.internalRenderHead(container);
				}

				//consider just direct children
				stream.skipToMatchingCloseTag(tag);
			}
		}
	}

	@Override
	protected Component findChildComponent(ComponentTag tag)
	{
		Component childComponent = super.findChildComponent(tag);

		return childComponent != null ? childComponent : resolve(this, null, tag);
	}
}