From c62b4e7904f306a977b9d19b404741551fe57c56 Mon Sep 17 00:00:00 2001 From: cuisongliu Date: Sun, 13 Oct 2024 21:26:29 +0800 Subject: [PATCH] feat(main): add broker config Signed-off-by: cuisongliu --- api/v1beta1/automq_types.go | 2 + cmd/main.go | 46 +- .../infra.cuisongliu.github.com_automqs.yaml | 4 + defaults/up.sh | 17 +- defaults/zz_generated_bindata.go | 4 +- .../infra.cuisongliu.github.com_automqs.yaml | 4 + .../automq-operator/templates/deployment.yaml | 5 + .../automq-operator/templates/service.yaml | 16 +- go.mod | 29 +- go.sum | 71 ++- internal/controller/automq_controller.go | 11 +- internal/controller/automq_controller_b.go | 484 ++++++++++++++++++ internal/controller/automq_controller_c.go | 22 +- 13 files changed, 680 insertions(+), 35 deletions(-) create mode 100644 internal/controller/automq_controller_b.go diff --git a/api/v1beta1/automq_types.go b/api/v1beta1/automq_types.go index 6f3eb2d..9c49fb4 100644 --- a/api/v1beta1/automq_types.go +++ b/api/v1beta1/automq_types.go @@ -157,6 +157,8 @@ type AutoMQSpec struct { ClusterID string `json:"clusterID,omitempty"` // Image is the image of the AutoMQ Image string `json:"image,omitempty"` + // NodePort is the node port of the AutoMQ + NodePort int32 `json:"nodePort,omitempty"` // Metrics is the metrics configuration for the AutoMQ Metrics MetricsSpec `json:"metrics,omitempty"` // Controller is the controller configuration for the AutoMQ diff --git a/cmd/main.go b/cmd/main.go index bf57535..724a7ea 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -18,7 +18,9 @@ package main import ( "flag" + v1 "k8s.io/api/core/v1" "os" + "sigs.k8s.io/controller-runtime/pkg/client" // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. @@ -26,6 +28,7 @@ import ( infrav1beta1 "github.com/cuisongliu/automq-operator/api/v1beta1" "github.com/cuisongliu/automq-operator/internal/controller" + "github.com/gin-gonic/gin" promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -111,8 +114,49 @@ func main() { os.Exit(1) } } + + if os.Getenv("OPERATOR_APIS_SVC_NAME") == "" { + setupLog.Error(err, "OPERATOR_APIS_SVC_NAME is empty") + os.Exit(1) + } + + if os.Getenv("NAMESPACE_NAME") == "" { + _ = os.Setenv("NAMESPACE_NAME", "default") + } + //+kubebuilder:scaffold:builder + ctx := ctrl.SetupSignalHandler() + + go func() { + if mgr.GetCache().WaitForCacheSync(ctx) { + setupLog.Info("cache sync success") + router := gin.Default() + router.GET("/api/v1/nodes/:name", func(c *gin.Context) { + name := c.Param("name") + node := &v1.Node{} + node.Name = name + if noe := mgr.GetClient().Get(ctx, client.ObjectKeyFromObject(node), node); noe != nil { + c.JSON(500, gin.H{"message": noe.Error()}) + return + } + nodeIP := "" + for _, addr := range node.Status.Addresses { + if addr.Type == v1.NodeInternalIP { + nodeIP = addr.Address + break + } + } + if nodeIP == "" { + c.JSON(500, gin.H{"message": "node ip not found"}) + return + } + c.String(200, nodeIP) + }) + router.Run(":9090") + } + }() + if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { setupLog.Error(err, "unable to set up health check") os.Exit(1) @@ -123,7 +167,7 @@ func main() { } setupLog.Info("starting manager") - if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { + if err := mgr.Start(ctx); err != nil { setupLog.Error(err, "problem running manager") os.Exit(1) } diff --git a/config/crd/bases/infra.cuisongliu.github.com_automqs.yaml b/config/crd/bases/infra.cuisongliu.github.com_automqs.yaml index 3c4c8d5..bb4d518 100644 --- a/config/crd/bases/infra.cuisongliu.github.com_automqs.yaml +++ b/config/crd/bases/infra.cuisongliu.github.com_automqs.yaml @@ -597,6 +597,10 @@ spec: required: - enable type: object + nodePort: + description: NodePort is the node port of the AutoMQ + format: int32 + type: integer s3: description: S3 is the S3 configuration for the AutoMQ properties: diff --git a/defaults/up.sh b/defaults/up.sh index c2dc5b7..e435234 100644 --- a/defaults/up.sh +++ b/defaults/up.sh @@ -186,15 +186,26 @@ kafka_monitor_ip() { # get private ip first local_private_ip="0.0.0.0" - advertised_ip="${local_private_ip}" + advertised_ip_port="${local_private_ip}:9092" + if [[ -n "${OPERATOR_APIS_ADDR}" ]]; then + node_ip=$(curl -f -s "${OPERATOR_APIS_ADDR}:/api/v1/nodes/${NODE_NAME}") + if [[ $? -eq 0 && -n "$node_ip" ]]; then + echo "kafka_monitor_ip: node_ip=${node_ip}" + advertised_ip_port="${node_ip}:${NODEPORT_DEFAULT_PORT}" + else + echo "Failed to retrieve node_ip from ${OPERATOR_APIS_ADDR}" + exit 1 + fi + fi + # change ip settings for this node if [[ "${process_role}" == "server" ]]; then setup_value "listeners" "PLAINTEXT://${local_private_ip}:9092,CONTROLLER://${local_private_ip}:9093" "${kafka_dir}/config/kraft/${process_role}.properties" - setup_value "advertised.listeners" "PLAINTEXT://${advertised_ip}:9092" "${kafka_dir}/config/kraft/${process_role}.properties" + setup_value "advertised.listeners" "PLAINTEXT://${advertised_ip_port}" "${kafka_dir}/config/kraft/${process_role}.properties" elif [[ "${process_role}" == "broker" ]]; then setup_value "listeners" "PLAINTEXT://${local_private_ip}:9092" "${kafka_dir}/config/kraft/${process_role}.properties" - setup_value "advertised.listeners" "PLAINTEXT://${advertised_ip}:9092" "${kafka_dir}/config/kraft/${process_role}.properties" + setup_value "advertised.listeners" "PLAINTEXT://${advertised_ip_port}" "${kafka_dir}/config/kraft/${process_role}.properties" elif [[ "${process_role}" == "controller" ]]; then setup_value "listeners" "CONTROLLER://${local_private_ip}:9093" "${kafka_dir}/config/kraft/${process_role}.properties" else diff --git a/defaults/zz_generated_bindata.go b/defaults/zz_generated_bindata.go index 627ed6e..8e056fc 100644 --- a/defaults/zz_generated_bindata.go +++ b/defaults/zz_generated_bindata.go @@ -67,7 +67,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _defaultsUpSh = "\x23\x21\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x65\x6e\x76\x20\x62\x61\x73\x68\x0a\x0a\x23\x20\x4c\x69\x63\x65\x6e\x73\x65\x64\x20\x74\x6f\x20\x74\x68\x65\x20\x41\x70\x61\x63\x68\x65\x20\x53\x6f\x66\x74\x77\x61\x72\x65\x20\x46\x6f\x75\x6e\x64\x61\x74\x69\x6f\x6e\x20\x28\x41\x53\x46\x29\x20\x75\x6e\x64\x65\x72\x20\x6f\x6e\x65\x20\x6f\x72\x20\x6d\x6f\x72\x65\x0a\x23\x20\x63\x6f\x6e\x74\x72\x69\x62\x75\x74\x6f\x72\x20\x6c\x69\x63\x65\x6e\x73\x65\x20\x61\x67\x72\x65\x65\x6d\x65\x6e\x74\x73\x2e\x20\x20\x53\x65\x65\x20\x74\x68\x65\x20\x4e\x4f\x54\x49\x43\x45\x20\x66\x69\x6c\x65\x20\x64\x69\x73\x74\x72\x69\x62\x75\x74\x65\x64\x20\x77\x69\x74\x68\x0a\x23\x20\x74\x68\x69\x73\x20\x77\x6f\x72\x6b\x20\x66\x6f\x72\x20\x61\x64\x64\x69\x74\x69\x6f\x6e\x61\x6c\x20\x69\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\x20\x72\x65\x67\x61\x72\x64\x69\x6e\x67\x20\x63\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x6f\x77\x6e\x65\x72\x73\x68\x69\x70\x2e\x0a\x23\x20\x54\x68\x65\x20\x41\x53\x46\x20\x6c\x69\x63\x65\x6e\x73\x65\x73\x20\x74\x68\x69\x73\x20\x66\x69\x6c\x65\x20\x74\x6f\x20\x59\x6f\x75\x20\x75\x6e\x64\x65\x72\x20\x74\x68\x65\x20\x41\x70\x61\x63\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x2c\x20\x56\x65\x72\x73\x69\x6f\x6e\x20\x32\x2e\x30\x0a\x23\x20\x28\x74\x68\x65\x20\x22\x4c\x69\x63\x65\x6e\x73\x65\x22\x29\x3b\x20\x79\x6f\x75\x20\x6d\x61\x79\x20\x6e\x6f\x74\x20\x75\x73\x65\x20\x74\x68\x69\x73\x20\x66\x69\x6c\x65\x20\x65\x78\x63\x65\x70\x74\x20\x69\x6e\x20\x63\x6f\x6d\x70\x6c\x69\x61\x6e\x63\x65\x20\x77\x69\x74\x68\x0a\x23\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x2e\x20\x20\x59\x6f\x75\x20\x6d\x61\x79\x20\x6f\x62\x74\x61\x69\x6e\x20\x61\x20\x63\x6f\x70\x79\x20\x6f\x66\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x20\x61\x74\x0a\x23\x0a\x23\x20\x20\x20\x20\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x70\x61\x63\x68\x65\x2e\x6f\x72\x67\x2f\x6c\x69\x63\x65\x6e\x73\x65\x73\x2f\x4c\x49\x43\x45\x4e\x53\x45\x2d\x32\x2e\x30\x0a\x23\x0a\x23\x20\x55\x6e\x6c\x65\x73\x73\x20\x72\x65\x71\x75\x69\x72\x65\x64\x20\x62\x79\x20\x61\x70\x70\x6c\x69\x63\x61\x62\x6c\x65\x20\x6c\x61\x77\x20\x6f\x72\x20\x61\x67\x72\x65\x65\x64\x20\x74\x6f\x20\x69\x6e\x20\x77\x72\x69\x74\x69\x6e\x67\x2c\x20\x73\x6f\x66\x74\x77\x61\x72\x65\x0a\x23\x20\x64\x69\x73\x74\x72\x69\x62\x75\x74\x65\x64\x20\x75\x6e\x64\x65\x72\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x20\x69\x73\x20\x64\x69\x73\x74\x72\x69\x62\x75\x74\x65\x64\x20\x6f\x6e\x20\x61\x6e\x20\x22\x41\x53\x20\x49\x53\x22\x20\x42\x41\x53\x49\x53\x2c\x0a\x23\x20\x57\x49\x54\x48\x4f\x55\x54\x20\x57\x41\x52\x52\x41\x4e\x54\x49\x45\x53\x20\x4f\x52\x20\x43\x4f\x4e\x44\x49\x54\x49\x4f\x4e\x53\x20\x4f\x46\x20\x41\x4e\x59\x20\x4b\x49\x4e\x44\x2c\x20\x65\x69\x74\x68\x65\x72\x20\x65\x78\x70\x72\x65\x73\x73\x20\x6f\x72\x20\x69\x6d\x70\x6c\x69\x65\x64\x2e\x0a\x23\x20\x53\x65\x65\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x73\x70\x65\x63\x69\x66\x69\x63\x20\x6c\x61\x6e\x67\x75\x61\x67\x65\x20\x67\x6f\x76\x65\x72\x6e\x69\x6e\x67\x20\x70\x65\x72\x6d\x69\x73\x73\x69\x6f\x6e\x73\x20\x61\x6e\x64\x0a\x23\x20\x6c\x69\x6d\x69\x74\x61\x74\x69\x6f\x6e\x73\x20\x75\x6e\x64\x65\x72\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x2e\x0a\x0a\x73\x63\x72\x69\x70\x74\x5f\x70\x61\x74\x68\x3d\x22\x24\x7b\x30\x7d\x22\x0a\x0a\x23\x20\x54\x68\x65\x20\x61\x62\x73\x6f\x6c\x75\x74\x65\x20\x70\x61\x74\x68\x20\x74\x6f\x20\x74\x68\x65\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x77\x68\x69\x63\x68\x20\x74\x68\x69\x73\x20\x73\x63\x72\x69\x70\x74\x20\x69\x73\x20\x69\x6e\x2e\x0a\x73\x74\x61\x72\x74\x5f\x64\x69\x72\x3d\x22\x24\x28\x63\x64\x20\x22\x24\x28\x64\x69\x72\x6e\x61\x6d\x65\x20\x22\x24\x7b\x42\x41\x53\x48\x5f\x53\x4f\x55\x52\x43\x45\x5b\x30\x5d\x7d\x22\x29\x22\x20\x26\x26\x20\x70\x77\x64\x29\x22\x0a\x0a\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x3d\x22\x24\x7b\x73\x74\x61\x72\x74\x5f\x64\x69\x72\x7d\x2f\x72\x75\x6e\x2e\x69\x6e\x66\x6f\x22\x0a\x0a\x23\x20\x54\x68\x65\x20\x61\x62\x73\x6f\x6c\x75\x74\x65\x20\x70\x61\x74\x68\x20\x74\x6f\x20\x74\x68\x65\x20\x72\x6f\x6f\x74\x20\x4b\x61\x66\x6b\x61\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x0a\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x3d\x22\x24\x28\x20\x63\x64\x20\x22\x24\x7b\x73\x74\x61\x72\x74\x5f\x64\x69\x72\x7d\x2f\x2e\x2e\x2f\x6b\x61\x66\x6b\x61\x22\x20\x26\x26\x20\x70\x77\x64\x20\x29\x22\x0a\x0a\x64\x61\x74\x61\x5f\x70\x61\x74\x68\x3d\x22\x2f\x64\x61\x74\x61\x2f\x6b\x61\x66\x6b\x61\x22\x0a\x0a\x23\x20\x45\x78\x69\x74\x20\x77\x69\x74\x68\x20\x61\x6e\x20\x65\x72\x72\x6f\x72\x20\x6d\x65\x73\x73\x61\x67\x65\x2e\x0a\x64\x69\x65\x28\x29\x20\x7b\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x24\x40\x22\x0a\x20\x20\x65\x78\x69\x74\x20\x31\x0a\x7d\x0a\x0a\x65\x63\x68\x6f\x5f\x61\x6e\x64\x5f\x64\x6f\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x63\x6d\x64\x3d\x22\x24\x7b\x40\x7d\x22\x0a\x20\x20\x20\x20\x65\x63\x68\x6f\x20\x22\x24\x7b\x63\x6d\x64\x7d\x22\x0a\x20\x20\x20\x20\x24\x7b\x63\x6d\x64\x7d\x0a\x7d\x0a\x0a\x23\x20\x52\x75\x6e\x20\x61\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x61\x6e\x64\x20\x64\x69\x65\x20\x69\x66\x20\x69\x74\x20\x66\x61\x69\x6c\x73\x2e\x0a\x23\x0a\x23\x20\x4f\x70\x74\x69\x6f\x6e\x61\x6c\x20\x66\x6c\x61\x67\x73\x3a\x0a\x23\x20\x2d\x76\x3a\x20\x70\x72\x69\x6e\x74\x20\x74\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x72\x75\x6e\x6e\x69\x6e\x67\x20\x69\x74\x2e\x0a\x23\x20\x2d\x6f\x3a\x20\x64\x69\x73\x70\x6c\x61\x79\x20\x74\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x6f\x75\x74\x70\x75\x74\x2e\x0a\x23\x20\x24\x40\x3a\x20\x54\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x74\x6f\x20\x72\x75\x6e\x2e\x0a\x6d\x75\x73\x74\x5f\x64\x6f\x28\x29\x20\x7b\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x76\x65\x72\x62\x6f\x73\x65\x3d\x30\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x6f\x75\x74\x70\x75\x74\x3d\x22\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x22\x0a\x20\x20\x77\x68\x69\x6c\x65\x20\x74\x72\x75\x65\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x63\x61\x73\x65\x20\x24\x7b\x31\x7d\x20\x69\x6e\x0a\x20\x20\x20\x20\x2d\x76\x29\x0a\x20\x20\x20\x20\x20\x20\x76\x65\x72\x62\x6f\x73\x65\x3d\x31\x0a\x20\x20\x20\x20\x20\x20\x73\x68\x69\x66\x74\x0a\x20\x20\x20\x20\x20\x20\x3b\x3b\x0a\x20\x20\x20\x20\x2d\x6f\x29\x0a\x20\x20\x20\x20\x20\x20\x6f\x75\x74\x70\x75\x74\x3d\x22\x2f\x64\x65\x76\x2f\x73\x74\x64\x6f\x75\x74\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x68\x69\x66\x74\x0a\x20\x20\x20\x20\x20\x20\x3b\x3b\x0a\x20\x20\x20\x20\x2a\x29\x20\x62\x72\x65\x61\x6b\x20\x3b\x3b\x0a\x20\x20\x20\x20\x65\x73\x61\x63\x0a\x20\x20\x64\x6f\x6e\x65\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x63\x6d\x64\x3d\x22\x24\x2a\x22\x0a\x20\x20\x5b\x5b\x20\x22\x24\x7b\x76\x65\x72\x62\x6f\x73\x65\x7d\x22\x20\x2d\x65\x71\x20\x31\x20\x5d\x5d\x20\x26\x26\x20\x65\x63\x68\x6f\x20\x22\x24\x7b\x63\x6d\x64\x7d\x22\x0a\x20\x20\x65\x76\x61\x6c\x20\x22\x24\x7b\x63\x6d\x64\x7d\x22\x20\x3e\x24\x7b\x6f\x75\x74\x70\x75\x74\x7d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x24\x7b\x31\x7d\x20\x66\x61\x69\x6c\x65\x64\x22\x0a\x7d\x0a\x0a\x23\x20\x44\x69\x73\x70\x6c\x61\x79\x20\x61\x20\x75\x73\x61\x67\x65\x20\x6d\x65\x73\x73\x61\x67\x65\x20\x6f\x6e\x20\x74\x68\x65\x20\x74\x65\x72\x6d\x69\x6e\x61\x6c\x20\x61\x6e\x64\x20\x65\x78\x69\x74\x2e\x0a\x23\x0a\x23\x20\x24\x31\x3a\x20\x54\x68\x65\x20\x65\x78\x69\x74\x20\x73\x74\x61\x74\x75\x73\x20\x74\x6f\x20\x75\x73\x65\x0a\x75\x73\x61\x67\x65\x28\x29\x20\x7b\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x65\x78\x69\x74\x5f\x73\x74\x61\x74\x75\x73\x3d\x22\x24\x7b\x31\x7d\x22\x0a\x20\x20\x63\x61\x74\x20\x3c\x3c\x45\x4f\x46\x0a\x73\x74\x61\x72\x74\x3a\x20\x61\x20\x74\x6f\x6f\x6c\x20\x66\x6f\x72\x20\x73\x74\x61\x72\x74\x69\x6e\x67\x20\x27\x41\x75\x74\x6f\x4d\x51\x20\x66\x6f\x72\x20\x41\x70\x61\x63\x68\x65\x20\x4b\x61\x66\x6b\x61\x20\x6f\x6e\x20\x53\x33\x27\x2e\x0a\x0a\x55\x73\x61\x67\x65\x3a\x20\x24\x7b\x73\x63\x72\x69\x70\x74\x5f\x70\x61\x74\x68\x7d\x20\x5b\x63\x6f\x6d\x6d\x61\x6e\x64\x5d\x20\x5b\x6f\x70\x74\x69\x6f\x6e\x73\x5d\x0a\x0a\x68\x65\x6c\x70\x7c\x2d\x68\x7c\x2d\x2d\x68\x65\x6c\x70\x0a\x20\x20\x20\x20\x44\x69\x73\x70\x6c\x61\x79\x20\x74\x68\x69\x73\x20\x68\x65\x6c\x70\x20\x6d\x65\x73\x73\x61\x67\x65\x0a\x75\x70\x20\x5b\x2d\x2d\x70\x72\x6f\x63\x65\x73\x73\x2e\x72\x6f\x6c\x65\x73\x20\x52\x4f\x4c\x45\x5d\x20\x5b\x2d\x2d\x6e\x6f\x64\x65\x2e\x69\x64\x20\x4e\x4f\x44\x45\x5f\x49\x44\x5d\x20\x5b\x2d\x2d\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x71\x75\x6f\x72\x75\x6d\x2e\x76\x6f\x74\x65\x72\x73\x20\x56\x4f\x54\x45\x52\x53\x5d\x0a\x20\x20\x20\x5b\x2d\x2d\x73\x33\x2e\x72\x65\x67\x69\x6f\x6e\x20\x52\x45\x47\x49\x4f\x4e\x5d\x20\x5b\x2d\x2d\x73\x33\x2e\x62\x75\x63\x6b\x65\x74\x20\x42\x55\x43\x4b\x45\x54\x5d\x20\x5b\x2d\x2d\x73\x33\x2e\x65\x6e\x64\x70\x6f\x69\x6e\x74\x20\x45\x4e\x44\x50\x4f\x49\x4e\x54\x5d\x0a\x20\x20\x20\x5b\x2d\x2d\x73\x33\x2e\x61\x63\x63\x65\x73\x73\x2e\x6b\x65\x79\x20\x41\x43\x43\x45\x53\x53\x5f\x4b\x45\x59\x5d\x20\x5b\x2d\x2d\x73\x33\x2e\x73\x65\x63\x72\x65\x74\x2e\x6b\x65\x79\x20\x53\x45\x43\x52\x45\x54\x5f\x4b\x45\x59\x5d\x0a\x20\x20\x20\x20\x73\x74\x61\x72\x74\x20\x6e\x6f\x64\x65\x2e\x0a\x45\x4f\x46\x0a\x20\x20\x65\x78\x69\x74\x20\x22\x24\x7b\x65\x78\x69\x74\x5f\x73\x74\x61\x74\x75\x73\x7d\x22\x0a\x7d\x0a\x0a\x23\x20\x43\x68\x65\x63\x6b\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x70\x72\x65\x73\x65\x6e\x63\x65\x20\x6f\x66\x20\x63\x65\x72\x74\x61\x69\x6e\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x2e\x0a\x23\x0a\x23\x20\x24\x40\x3a\x20\x54\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x20\x74\x6f\x20\x63\x68\x65\x63\x6b\x20\x66\x6f\x72\x2e\x20\x20\x54\x68\x69\x73\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x20\x77\x69\x6c\x6c\x20\x64\x69\x65\x20\x69\x66\x20\x61\x6e\x79\x20\x6f\x66\x20\x74\x68\x65\x73\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x20\x61\x72\x65\x20\x6e\x6f\x74\x20\x66\x6f\x75\x6e\x64\x20\x62\x79\x0a\x23\x20\x20\x20\x20\x20\x20\x20\x74\x68\x65\x20\x27\x77\x68\x69\x63\x68\x27\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x2e\x0a\x72\x65\x71\x75\x69\x72\x65\x5f\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x28\x29\x20\x7b\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x63\x6d\x64\x73\x3d\x28\x22\x24\x40\x22\x29\x0a\x20\x20\x66\x6f\x72\x20\x63\x6d\x64\x20\x69\x6e\x20\x22\x24\x7b\x63\x6d\x64\x73\x5b\x40\x5d\x7d\x22\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x77\x68\x69\x63\x68\x20\x2d\x2d\x20\x22\x24\x7b\x63\x6d\x64\x7d\x22\x20\x26\x3e\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x59\x6f\x75\x20\x6d\x75\x73\x74\x20\x69\x6e\x73\x74\x61\x6c\x6c\x20\x24\x7b\x63\x6d\x64\x7d\x20\x74\x6f\x20\x72\x75\x6e\x20\x74\x68\x69\x73\x20\x73\x63\x72\x69\x70\x74\x2e\x22\x0a\x20\x20\x64\x6f\x6e\x65\x0a\x7d\x0a\x0a\x23\x20\x53\x65\x74\x20\x61\x20\x67\x6c\x6f\x62\x61\x6c\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x74\x6f\x20\x61\x20\x76\x61\x6c\x75\x65\x2e\x0a\x23\x0a\x23\x20\x24\x31\x3a\x20\x54\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x6e\x61\x6d\x65\x20\x74\x6f\x20\x73\x65\x74\x2e\x20\x20\x54\x68\x69\x73\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x20\x77\x69\x6c\x6c\x20\x64\x69\x65\x20\x69\x66\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x68\x61\x73\x20\x61\x20\x76\x61\x6c\x75\x65\x2e\x20\x20\x54\x68\x65\x0a\x23\x20\x20\x20\x20\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x77\x69\x6c\x6c\x20\x62\x65\x20\x6d\x61\x64\x65\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x74\x6f\x20\x70\x72\x65\x76\x65\x6e\x74\x20\x61\x6e\x79\x20\x66\x75\x74\x75\x72\x65\x20\x6d\x6f\x64\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x73\x2e\x0a\x23\x20\x24\x32\x3a\x20\x54\x68\x65\x20\x76\x61\x6c\x75\x65\x20\x74\x6f\x20\x73\x65\x74\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x74\x6f\x2e\x20\x20\x54\x68\x69\x73\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x20\x77\x69\x6c\x6c\x20\x64\x69\x65\x20\x69\x66\x20\x74\x68\x65\x20\x76\x61\x6c\x75\x65\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x20\x6f\x72\x20\x73\x74\x61\x72\x74\x73\x0a\x23\x20\x20\x20\x20\x20\x77\x69\x74\x68\x20\x61\x20\x64\x61\x73\x68\x2e\x0a\x23\x20\x24\x33\x3a\x20\x41\x20\x68\x75\x6d\x61\x6e\x2d\x72\x65\x61\x64\x61\x62\x6c\x65\x20\x64\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x6f\x66\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x2e\x0a\x73\x65\x74\x5f\x6f\x6e\x63\x65\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x6b\x65\x79\x3d\x22\x24\x7b\x31\x7d\x22\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x76\x61\x6c\x75\x65\x3d\x22\x24\x7b\x32\x7d\x22\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x77\x68\x61\x74\x3d\x22\x24\x7b\x33\x7d\x22\x0a\x20\x20\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x21\x6b\x65\x79\x7d\x22\x20\x5d\x5d\x20\x26\x26\x20\x64\x69\x65\x20\x22\x45\x72\x72\x6f\x72\x3a\x20\x6d\x6f\x72\x65\x20\x74\x68\x61\x6e\x20\x6f\x6e\x65\x20\x76\x61\x6c\x75\x65\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64\x20\x66\x6f\x72\x20\x24\x7b\x77\x68\x61\x74\x7d\x2e\x22\x0a\x20\x20\x20\x20\x76\x65\x72\x69\x66\x79\x5f\x63\x6f\x6d\x6d\x61\x6e\x64\x5f\x6c\x69\x6e\x65\x5f\x61\x72\x67\x75\x6d\x65\x6e\x74\x20\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x22\x24\x7b\x77\x68\x61\x74\x7d\x22\x0a\x20\x20\x20\x20\x23\x20\x49\x74\x20\x77\x6f\x75\x6c\x64\x20\x62\x65\x20\x62\x65\x74\x74\x65\x72\x20\x74\x6f\x20\x75\x73\x65\x20\x64\x65\x63\x6c\x61\x72\x65\x20\x2d\x67\x2c\x20\x62\x75\x74\x20\x6f\x6c\x64\x65\x72\x20\x62\x61\x73\x68\x20\x76\x65\x72\x73\x69\x6f\x6e\x73\x20\x64\x6f\x6e\x27\x74\x20\x73\x75\x70\x70\x6f\x72\x74\x20\x69\x74\x2e\x0a\x20\x20\x20\x20\x65\x78\x70\x6f\x72\x74\x20\x22\x24\x7b\x6b\x65\x79\x7d\x22\x3d\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x0a\x7d\x0a\x0a\x23\x20\x56\x65\x72\x69\x66\x79\x20\x74\x68\x61\x74\x20\x61\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x2d\x6c\x69\x6e\x65\x20\x61\x72\x67\x75\x6d\x65\x6e\x74\x20\x69\x73\x20\x70\x72\x65\x73\x65\x6e\x74\x20\x61\x6e\x64\x20\x64\x6f\x65\x73\x20\x6e\x6f\x74\x20\x73\x74\x61\x72\x74\x20\x77\x69\x74\x68\x20\x61\x20\x73\x6c\x61\x73\x68\x2e\x0a\x23\x0a\x23\x20\x24\x31\x3a\x20\x54\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x2d\x6c\x69\x6e\x65\x20\x61\x72\x67\x75\x6d\x65\x6e\x74\x20\x74\x6f\x20\x76\x65\x72\x69\x66\x79\x2e\x0a\x23\x20\x24\x32\x3a\x20\x41\x20\x68\x75\x6d\x61\x6e\x2d\x72\x65\x61\x64\x61\x62\x6c\x65\x20\x64\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x6f\x66\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x2e\x0a\x76\x65\x72\x69\x66\x79\x5f\x63\x6f\x6d\x6d\x61\x6e\x64\x5f\x6c\x69\x6e\x65\x5f\x61\x72\x67\x75\x6d\x65\x6e\x74\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x76\x61\x6c\x75\x65\x3d\x22\x24\x7b\x31\x7d\x22\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x77\x68\x61\x74\x3d\x22\x24\x7b\x32\x7d\x22\x0a\x20\x20\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x45\x72\x72\x6f\x72\x3a\x20\x6e\x6f\x20\x76\x61\x6c\x75\x65\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64\x20\x66\x6f\x72\x20\x24\x7b\x77\x68\x61\x74\x7d\x22\x0a\x20\x20\x20\x20\x5b\x5b\x20\x24\x7b\x76\x61\x6c\x75\x65\x7d\x20\x3d\x3d\x20\x2d\x2a\x20\x5d\x5d\x20\x26\x26\x20\x64\x69\x65\x20\x22\x45\x72\x72\x6f\x72\x3a\x20\x69\x6e\x76\x61\x6c\x69\x64\x20\x76\x61\x6c\x75\x65\x20\x24\x7b\x76\x61\x6c\x75\x65\x7d\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64\x20\x66\x6f\x72\x20\x24\x7b\x77\x68\x61\x74\x7d\x22\x0a\x7d\x0a\x0a\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x28\x29\x20\x7b\x0a\x20\x20\x6b\x65\x79\x3d\x24\x31\x0a\x20\x20\x76\x61\x6c\x75\x65\x3d\x24\x32\x0a\x20\x20\x66\x69\x6c\x65\x3d\x24\x33\x0a\x20\x20\x23\x20\x72\x65\x70\x6c\x61\x63\x65\x20\x73\x70\x65\x63\x69\x61\x6c\x20\x63\x68\x61\x72\x61\x63\x74\x65\x72\x73\x0a\x20\x20\x76\x61\x6c\x75\x65\x3d\x24\x7b\x76\x61\x6c\x75\x65\x2f\x2f\x26\x2f\x5c\x5c\x26\x7d\x0a\x20\x20\x76\x61\x6c\x75\x65\x3d\x24\x7b\x76\x61\x6c\x75\x65\x2f\x2f\x23\x2f\x2f\x5c\x5c\x23\x2f\x7d\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x3a\x20\x6b\x65\x79\x3d\x24\x7b\x6b\x65\x79\x7d\x2c\x20\x76\x61\x6c\x75\x65\x3d\x24\x7b\x76\x61\x6c\x75\x65\x7d\x2c\x20\x66\x69\x6c\x65\x3d\x24\x7b\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x73\x65\x64\x20\x2d\x69\x20\x22\x73\x7c\x5e\x24\x7b\x6b\x65\x79\x7d\x3d\x2e\x2a\x24\x7c\x24\x7b\x6b\x65\x79\x7d\x3d\x24\x7b\x76\x61\x6c\x75\x65\x7d\x7c\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x7d\x22\x0a\x7d\x0a\x0a\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x28\x29\x20\x7b\x0a\x20\x20\x6b\x65\x79\x3d\x24\x31\x0a\x20\x20\x76\x61\x6c\x75\x65\x3d\x24\x32\x0a\x20\x20\x66\x69\x6c\x65\x3d\x24\x33\x0a\x20\x20\x69\x66\x20\x67\x72\x65\x70\x20\x2d\x71\x20\x22\x5e\x24\x7b\x6b\x65\x79\x7d\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x7d\x22\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x24\x7b\x6b\x65\x79\x7d\x22\x20\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x65\x6c\x73\x65\x0a\x20\x20\x20\x20\x65\x63\x68\x6f\x20\x22\x24\x7b\x6b\x65\x79\x7d\x3d\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x7c\x20\x74\x65\x65\x20\x2d\x61\x20\x22\x24\x7b\x66\x69\x6c\x65\x7d\x22\x20\x3e\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x0a\x20\x20\x66\x69\x0a\x7d\x0a\x0a\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x61\x6c\x6c\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x74\x6f\x70\x69\x63\x22\x20\x22\x41\x75\x74\x6f\x42\x61\x6c\x61\x6e\x63\x65\x72\x4d\x65\x74\x72\x69\x63\x73\x52\x65\x70\x6f\x72\x74\x65\x72\x54\x6f\x70\x69\x63\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x74\x6f\x70\x69\x63\x2e\x6e\x75\x6d\x2e\x70\x61\x72\x74\x69\x74\x69\x6f\x6e\x73\x22\x20\x22\x31\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x7d\x0a\x0a\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x5f\x6f\x6e\x6c\x79\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x65\x6e\x61\x62\x6c\x65\x22\x20\x22\x74\x72\x75\x65\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x65\x78\x63\x6c\x75\x64\x65\x2e\x74\x6f\x70\x69\x63\x73\x22\x20\x22\x5f\x5f\x63\x6f\x6e\x73\x75\x6d\x65\x72\x5f\x6f\x66\x66\x73\x65\x74\x73\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x7d\x0a\x0a\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x62\x72\x6f\x6b\x65\x72\x5f\x6f\x6e\x6c\x79\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6d\x65\x74\x72\x69\x63\x2e\x72\x65\x70\x6f\x72\x74\x65\x72\x73\x22\x20\x22\x6b\x61\x66\x6b\x61\x2e\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x6d\x65\x74\x72\x69\x63\x73\x72\x65\x70\x6f\x72\x74\x65\x72\x2e\x41\x75\x74\x6f\x42\x61\x6c\x61\x6e\x63\x65\x72\x4d\x65\x74\x72\x69\x63\x73\x52\x65\x70\x6f\x72\x74\x65\x72\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x7d\x0a\x0a\x74\x75\x72\x6e\x5f\x6f\x6e\x5f\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x72\x6f\x6c\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x32\x0a\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x61\x6c\x6c\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x62\x72\x6f\x6b\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x62\x72\x6f\x6b\x65\x72\x5f\x6f\x6e\x6c\x79\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x5f\x6f\x6e\x6c\x79\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x73\x65\x72\x76\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x5f\x6f\x6e\x6c\x79\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x62\x72\x6f\x6b\x65\x72\x5f\x6f\x6e\x6c\x79\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x66\x69\x0a\x7d\x0a\x0a\x0a\x23\x20\x6d\x6f\x6e\x69\x74\x6f\x72\x20\x61\x6e\x64\x20\x63\x68\x61\x6e\x67\x65\x20\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x20\x69\x70\x20\x66\x6f\x72\x20\x6b\x61\x66\x6b\x61\x0a\x6b\x61\x66\x6b\x61\x5f\x6d\x6f\x6e\x69\x74\x6f\x72\x5f\x69\x70\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x3d\x24\x28\x67\x72\x65\x70\x20\x22\x72\x6f\x6c\x65\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x20\x7c\x20\x61\x77\x6b\x20\x2d\x46\x3d\x20\x27\x7b\x70\x72\x69\x6e\x74\x20\x24\x32\x7d\x27\x29\x0a\x20\x20\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x6b\x61\x66\x6b\x61\x5f\x64\x6f\x77\x6e\x3a\x20\x66\x61\x69\x6c\x65\x64\x20\x74\x6f\x20\x67\x65\x74\x20\x6e\x6f\x64\x65\x20\x72\x6f\x6c\x65\x22\x0a\x0a\x20\x20\x20\x20\x23\x20\x67\x65\x74\x20\x70\x72\x69\x76\x61\x74\x65\x20\x69\x70\x20\x66\x69\x72\x73\x74\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x3d\x22\x30\x2e\x30\x2e\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x5f\x69\x70\x3d\x22\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x22\x0a\x0a\x20\x20\x20\x20\x23\x20\x63\x68\x61\x6e\x67\x65\x20\x69\x70\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x66\x6f\x72\x20\x74\x68\x69\x73\x20\x6e\x6f\x64\x65\x0a\x20\x20\x20\x20\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x73\x65\x72\x76\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x50\x4c\x41\x49\x4e\x54\x45\x58\x54\x3a\x2f\x2f\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x32\x2c\x43\x4f\x4e\x54\x52\x4f\x4c\x4c\x45\x52\x3a\x2f\x2f\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x33\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x2e\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x50\x4c\x41\x49\x4e\x54\x45\x58\x54\x3a\x2f\x2f\x24\x7b\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x5f\x69\x70\x7d\x3a\x39\x30\x39\x32\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x62\x72\x6f\x6b\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x50\x4c\x41\x49\x4e\x54\x45\x58\x54\x3a\x2f\x2f\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x32\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x2e\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x50\x4c\x41\x49\x4e\x54\x45\x58\x54\x3a\x2f\x2f\x24\x7b\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x5f\x69\x70\x7d\x3a\x39\x30\x39\x32\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x43\x4f\x4e\x54\x52\x4f\x4c\x4c\x45\x52\x3a\x2f\x2f\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x33\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x65\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x64\x69\x65\x20\x22\x6b\x61\x66\x6b\x61\x5f\x6d\x6f\x6e\x69\x74\x6f\x72\x5f\x69\x70\x3a\x20\x75\x6e\x6b\x6e\x6f\x77\x6e\x20\x70\x72\x6f\x63\x65\x73\x73\x20\x72\x6f\x6c\x65\x20\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x0a\x20\x20\x20\x20\x66\x69\x0a\x7d\x0a\x0a\x63\x6f\x6e\x66\x69\x67\x75\x72\x65\x5f\x66\x72\x6f\x6d\x5f\x65\x6e\x76\x69\x72\x6f\x6e\x6d\x65\x6e\x74\x5f\x76\x61\x72\x69\x61\x62\x6c\x65\x73\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x23\x20\x4c\x69\x73\x74\x20\x6f\x66\x20\x73\x70\x65\x63\x69\x61\x6c\x20\x63\x61\x73\x65\x73\x20\x74\x6f\x20\x61\x70\x70\x6c\x79\x20\x74\x6f\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x73\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x2d\x72\x20\x65\x78\x63\x65\x70\x74\x69\x6f\x6e\x5f\x72\x65\x67\x65\x78\x70\x73\x3d\x28\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x22\x73\x2f\x73\x61\x73\x6c\x5c\x2e\x73\x73\x6c\x2f\x73\x61\x73\x6c\x5f\x73\x73\x6c\x2f\x67\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x22\x73\x2f\x73\x61\x73\x6c\x5c\x2e\x70\x6c\x61\x69\x6e\x74\x65\x78\x74\x2f\x73\x61\x73\x6c\x5f\x70\x6c\x61\x69\x6e\x74\x65\x78\x74\x2f\x67\x22\x0a\x20\x20\x20\x20\x29\x0a\x20\x20\x20\x20\x23\x20\x4d\x61\x70\x20\x65\x6e\x76\x69\x72\x6f\x6e\x6d\x65\x6e\x74\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x73\x20\x74\x6f\x20\x63\x6f\x6e\x66\x69\x67\x20\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x76\x61\x72\x20\x69\x6e\x20\x22\x24\x7b\x21\x4b\x41\x46\x4b\x41\x5f\x43\x46\x47\x5f\x40\x7d\x22\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6b\x65\x79\x3d\x22\x24\x28\x65\x63\x68\x6f\x20\x22\x24\x76\x61\x72\x22\x20\x7c\x20\x73\x65\x64\x20\x2d\x65\x20\x27\x73\x2f\x5e\x4b\x41\x46\x4b\x41\x5f\x43\x46\x47\x5f\x2f\x2f\x67\x27\x20\x2d\x65\x20\x27\x73\x2f\x5f\x2f\x5c\x2e\x2f\x67\x27\x20\x7c\x20\x74\x72\x20\x27\x5b\x3a\x75\x70\x70\x65\x72\x3a\x5d\x27\x20\x27\x5b\x3a\x6c\x6f\x77\x65\x72\x3a\x5d\x27\x29\x22\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x23\x20\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x63\x61\x6d\x65\x6c\x20\x63\x61\x73\x65\x20\x69\x6e\x20\x74\x68\x69\x73\x20\x65\x6e\x76\x69\x72\x6f\x6e\x6d\x65\x6e\x74\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x5b\x5b\x20\x22\x24\x76\x61\x72\x22\x20\x3d\x3d\x20\x22\x4b\x41\x46\x4b\x41\x5f\x43\x46\x47\x5f\x5a\x4f\x4f\x4b\x45\x45\x50\x45\x52\x5f\x43\x4c\x49\x45\x4e\x54\x43\x4e\x58\x4e\x53\x4f\x43\x4b\x45\x54\x22\x20\x5d\x5d\x20\x26\x26\x20\x6b\x65\x79\x3d\x22\x7a\x6f\x6f\x6b\x65\x65\x70\x65\x72\x2e\x63\x6c\x69\x65\x6e\x74\x43\x6e\x78\x6e\x53\x6f\x63\x6b\x65\x74\x22\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x23\x20\x41\x70\x70\x6c\x79\x20\x65\x78\x63\x65\x70\x74\x69\x6f\x6e\x20\x72\x65\x67\x65\x78\x70\x73\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x72\x65\x67\x65\x78\x20\x69\x6e\x20\x22\x24\x7b\x65\x78\x63\x65\x70\x74\x69\x6f\x6e\x5f\x72\x65\x67\x65\x78\x70\x73\x5b\x40\x5d\x7d\x22\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6b\x65\x79\x3d\x22\x24\x28\x65\x63\x68\x6f\x20\x22\x24\x6b\x65\x79\x22\x20\x7c\x20\x73\x65\x64\x20\x22\x24\x72\x65\x67\x65\x78\x22\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x64\x6f\x6e\x65\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x76\x61\x6c\x75\x65\x3d\x22\x24\x7b\x21\x76\x61\x72\x7d\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x24\x7b\x6b\x65\x79\x7d\x22\x20\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x64\x6f\x6e\x65\x0a\x7d\x0a\x0a\x6b\x61\x66\x6b\x61\x5f\x75\x70\x28\x29\x20\x7b\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x6b\x61\x66\x6b\x61\x5f\x75\x70\x3a\x20\x73\x74\x61\x72\x74\x22\x0a\x0a\x20\x20\x77\x68\x69\x6c\x65\x20\x5b\x5b\x20\x24\x23\x20\x2d\x67\x65\x20\x31\x20\x5d\x5d\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x20\x20\x63\x61\x73\x65\x20\x22\x24\x7b\x31\x7d\x22\x20\x69\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x70\x72\x6f\x63\x65\x73\x73\x2e\x72\x6f\x6c\x65\x73\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x72\x6f\x6c\x65\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x6e\x6f\x64\x65\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x6e\x6f\x64\x65\x2e\x69\x64\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x6e\x6f\x64\x65\x5f\x69\x64\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x69\x64\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x6e\x6f\x64\x65\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x71\x75\x6f\x72\x75\x6d\x2e\x76\x6f\x74\x65\x72\x73\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x71\x75\x6f\x72\x75\x6d\x5f\x76\x6f\x74\x65\x72\x73\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x20\x71\x75\x6f\x72\x75\x6d\x20\x76\x6f\x74\x65\x72\x73\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x72\x65\x67\x69\x6f\x6e\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x72\x65\x67\x69\x6f\x6e\x73\x20\x6f\x66\x20\x73\x33\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x62\x75\x63\x6b\x65\x74\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x62\x75\x63\x6b\x65\x74\x20\x6e\x61\x6d\x65\x20\x6f\x66\x20\x73\x33\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x63\x6c\x75\x73\x74\x65\x72\x2e\x69\x64\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x63\x6c\x75\x73\x74\x65\x72\x5f\x69\x64\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x6b\x61\x66\x6b\x61\x20\x63\x6c\x75\x73\x74\x65\x72\x20\x69\x64\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x61\x63\x63\x65\x73\x73\x2e\x6b\x65\x79\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x61\x63\x63\x65\x73\x73\x5f\x6b\x65\x79\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x73\x33\x20\x61\x63\x63\x65\x73\x73\x20\x6b\x65\x79\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x73\x65\x63\x72\x65\x74\x2e\x6b\x65\x79\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x73\x65\x63\x72\x65\x74\x5f\x6b\x65\x79\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x73\x33\x20\x73\x65\x63\x72\x65\x74\x20\x6b\x65\x79\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x65\x6e\x64\x70\x6f\x69\x6e\x74\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x73\x33\x20\x65\x6e\x64\x70\x6f\x69\x6e\x74\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x70\x61\x74\x68\x2e\x73\x74\x79\x6c\x65\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x73\x33\x20\x70\x61\x74\x68\x20\x73\x74\x79\x6c\x65\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x65\x73\x61\x63\x0a\x20\x20\x64\x6f\x6e\x65\x0a\x0a\x20\x20\x70\x69\x64\x3d\x24\x28\x6a\x63\x6d\x64\x20\x7c\x20\x67\x72\x65\x70\x20\x2d\x65\x20\x6b\x61\x66\x6b\x61\x2e\x4b\x61\x66\x6b\x61\x20\x7c\x20\x61\x77\x6b\x20\x27\x7b\x70\x72\x69\x6e\x74\x20\x24\x31\x7d\x27\x29\x0a\x20\x20\x69\x66\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x70\x69\x64\x7d\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x65\x63\x68\x6f\x20\x22\x6b\x61\x66\x6b\x61\x5f\x75\x70\x3a\x20\x6b\x61\x66\x6b\x61\x20\x69\x73\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x72\x75\x6e\x6e\x69\x6e\x67\x2c\x20\x70\x69\x64\x3d\x24\x7b\x70\x69\x64\x7d\x22\x0a\x20\x20\x20\x20\x20\x20\x65\x78\x69\x74\x20\x30\x0a\x20\x20\x66\x69\x0a\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x6e\x6f\x64\x65\x5f\x69\x64\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x6e\x6f\x64\x65\x5f\x69\x64\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x71\x75\x6f\x72\x75\x6d\x5f\x76\x6f\x74\x65\x72\x73\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x71\x75\x6f\x72\x75\x6d\x5f\x76\x6f\x74\x65\x72\x73\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x3d\x22\x24\x7b\x41\x57\x53\x5f\x44\x45\x46\x41\x55\x4c\x54\x5f\x52\x45\x47\x49\x4f\x4e\x7d\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x61\x63\x63\x65\x73\x73\x5f\x6b\x65\x79\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x73\x33\x5f\x61\x63\x63\x65\x73\x73\x5f\x6b\x65\x79\x3d\x22\x24\x7b\x4b\x41\x46\x4b\x41\x5f\x53\x33\x5f\x41\x43\x43\x45\x53\x53\x5f\x4b\x45\x59\x7d\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x73\x65\x63\x72\x65\x74\x5f\x6b\x65\x79\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x73\x33\x5f\x73\x65\x63\x72\x65\x74\x5f\x6b\x65\x79\x3d\x22\x24\x7b\x4b\x41\x46\x4b\x41\x5f\x53\x33\x5f\x53\x45\x43\x52\x45\x54\x5f\x4b\x45\x59\x7d\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x63\x6c\x75\x73\x74\x65\x72\x5f\x69\x64\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x63\x6c\x75\x73\x74\x65\x72\x5f\x69\x64\x3d\x22\x72\x5a\x64\x45\x30\x44\x6a\x5a\x53\x72\x71\x79\x39\x36\x50\x58\x72\x4d\x55\x5a\x56\x77\x22\x0a\x0a\x20\x20\x66\x6f\x72\x20\x72\x6f\x6c\x65\x20\x69\x6e\x20\x22\x62\x72\x6f\x6b\x65\x72\x22\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x22\x20\x22\x73\x65\x72\x76\x65\x72\x22\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6e\x6f\x64\x65\x2e\x69\x64\x22\x20\x22\x24\x7b\x6e\x6f\x64\x65\x5f\x69\x64\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x71\x75\x6f\x72\x75\x6d\x2e\x76\x6f\x74\x65\x72\x73\x22\x20\x22\x24\x7b\x71\x75\x6f\x72\x75\x6d\x5f\x76\x6f\x74\x65\x72\x73\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x73\x33\x2e\x64\x61\x74\x61\x2e\x62\x75\x63\x6b\x65\x74\x73\x22\x20\x22\x30\x40\x73\x33\x3a\x2f\x2f\x24\x7b\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x7d\x3f\x72\x65\x67\x69\x6f\x6e\x3d\x24\x7b\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x7d\x26\x65\x6e\x64\x70\x6f\x69\x6e\x74\x3d\x24\x7b\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x7d\x26\x61\x75\x74\x68\x54\x79\x70\x65\x3d\x73\x74\x61\x74\x69\x63\x26\x70\x61\x74\x68\x53\x74\x79\x6c\x65\x3d\x24\x7b\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x73\x33\x2e\x6f\x70\x73\x2e\x62\x75\x63\x6b\x65\x74\x73\x22\x20\x22\x30\x40\x73\x33\x3a\x2f\x2f\x24\x7b\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x7d\x3f\x72\x65\x67\x69\x6f\x6e\x3d\x24\x7b\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x7d\x26\x65\x6e\x64\x70\x6f\x69\x6e\x74\x3d\x24\x7b\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x7d\x26\x61\x75\x74\x68\x54\x79\x70\x65\x3d\x73\x74\x61\x74\x69\x63\x26\x70\x61\x74\x68\x53\x74\x79\x6c\x65\x3d\x24\x7b\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6c\x6f\x67\x2e\x64\x69\x72\x73\x22\x20\x22\x24\x7b\x64\x61\x74\x61\x5f\x70\x61\x74\x68\x7d\x2f\x6b\x72\x61\x66\x74\x2d\x24\x7b\x72\x6f\x6c\x65\x7d\x2d\x6c\x6f\x67\x73\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x73\x33\x2e\x77\x61\x6c\x2e\x70\x61\x74\x68\x22\x20\x22\x30\x40\x66\x69\x6c\x65\x3a\x2f\x2f\x24\x7b\x64\x61\x74\x61\x5f\x70\x61\x74\x68\x7d\x2f\x77\x61\x6c\x3f\x63\x61\x70\x61\x63\x69\x74\x79\x3d\x32\x31\x34\x37\x34\x38\x33\x36\x34\x38\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x23\x20\x74\x75\x72\x6e\x20\x6f\x6e\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x0a\x20\x20\x20\x20\x20\x20\x74\x75\x72\x6e\x5f\x6f\x6e\x5f\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x20\x22\x24\x7b\x72\x6f\x6c\x65\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x64\x6f\x6e\x65\x0a\x0a\x20\x20\x69\x66\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x4b\x41\x46\x4b\x41\x5f\x48\x45\x41\x50\x5f\x4f\x50\x54\x53\x7d\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x6b\x61\x66\x6b\x61\x5f\x68\x65\x61\x70\x5f\x6f\x70\x74\x73\x3d\x22\x24\x7b\x4b\x41\x46\x4b\x41\x5f\x48\x45\x41\x50\x5f\x4f\x50\x54\x53\x7d\x22\x0a\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x62\x72\x6f\x6b\x65\x72\x22\x20\x7c\x7c\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x73\x65\x72\x76\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x6b\x61\x66\x6b\x61\x5f\x68\x65\x61\x70\x5f\x6f\x70\x74\x73\x3d\x22\x2d\x58\x6d\x73\x31\x67\x20\x2d\x58\x6d\x78\x31\x67\x20\x2d\x58\x58\x3a\x4d\x65\x74\x61\x73\x70\x61\x63\x65\x53\x69\x7a\x65\x3d\x39\x36\x6d\x20\x2d\x58\x58\x3a\x4d\x61\x78\x44\x69\x72\x65\x63\x74\x4d\x65\x6d\x6f\x72\x79\x53\x69\x7a\x65\x3d\x31\x47\x22\x0a\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x6b\x61\x66\x6b\x61\x5f\x68\x65\x61\x70\x5f\x6f\x70\x74\x73\x3d\x22\x2d\x58\x6d\x73\x31\x67\x20\x2d\x58\x6d\x78\x31\x67\x20\x2d\x58\x58\x3a\x4d\x65\x74\x61\x73\x70\x61\x63\x65\x53\x69\x7a\x65\x3d\x39\x36\x6d\x22\x0a\x20\x20\x65\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x64\x69\x65\x20\x22\x6b\x61\x66\x6b\x61\x5f\x73\x74\x61\x72\x74\x5f\x75\x70\x3a\x20\x75\x6e\x6b\x6e\x6f\x77\x6e\x20\x70\x72\x6f\x63\x65\x73\x73\x20\x72\x6f\x6c\x65\x20\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x0a\x20\x20\x66\x69\x0a\x20\x20\x65\x78\x70\x6f\x72\x74\x20\x4b\x41\x46\x4b\x41\x5f\x48\x45\x41\x50\x5f\x4f\x50\x54\x53\x3d\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x68\x65\x61\x70\x5f\x6f\x70\x74\x73\x7d\x22\x0a\x0a\x20\x20\x23\x20\x61\x64\x64\x20\x74\x68\x69\x73\x20\x6e\x6f\x64\x65\x27\x73\x20\x69\x6e\x66\x6f\x20\x74\x6f\x20\x72\x75\x6e\x2e\x69\x6e\x66\x6f\x0a\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6e\x6f\x64\x65\x2e\x69\x64\x22\x20\x22\x24\x7b\x6e\x6f\x64\x65\x5f\x69\x64\x7d\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x72\x6f\x6c\x65\x22\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6b\x61\x66\x6b\x61\x2e\x62\x61\x73\x65\x2e\x70\x61\x74\x68\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6b\x61\x66\x6b\x61\x2e\x64\x61\x74\x61\x2e\x70\x61\x74\x68\x22\x20\x22\x24\x7b\x64\x61\x74\x61\x5f\x70\x61\x74\x68\x7d\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x0a\x0a\x20\x20\x23\x20\x63\x68\x61\x6e\x67\x65\x20\x69\x70\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x68\x65\x72\x65\x0a\x20\x20\x6b\x61\x66\x6b\x61\x5f\x6d\x6f\x6e\x69\x74\x6f\x72\x5f\x69\x70\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x6b\x61\x66\x6b\x61\x5f\x75\x70\x3a\x20\x69\x70\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x63\x68\x61\x6e\x67\x65\x64\x22\x0a\x0a\x20\x20\x23\x20\x6f\x76\x65\x72\x72\x69\x64\x65\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x66\x72\x6f\x6d\x20\x65\x6e\x76\x0a\x20\x20\x63\x6f\x6e\x66\x69\x67\x75\x72\x65\x5f\x66\x72\x6f\x6d\x5f\x65\x6e\x76\x69\x72\x6f\x6e\x6d\x65\x6e\x74\x5f\x76\x61\x72\x69\x61\x62\x6c\x65\x73\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x0a\x20\x20\x23\x20\x44\x69\x73\x61\x62\x6c\x65\x20\x74\x68\x65\x20\x64\x65\x66\x61\x75\x6c\x74\x20\x63\x6f\x6e\x73\x6f\x6c\x65\x20\x6c\x6f\x67\x67\x65\x72\x20\x69\x6e\x20\x66\x61\x76\x6f\x75\x72\x20\x6f\x66\x20\x4b\x61\x66\x6b\x61\x41\x70\x70\x65\x6e\x64\x65\x72\x20\x28\x77\x68\x69\x63\x68\x20\x70\x72\x6f\x76\x69\x64\x65\x73\x20\x74\x68\x65\x20\x65\x78\x61\x63\x74\x20\x6f\x75\x74\x70\x75\x74\x29\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x6c\x6f\x67\x34\x6a\x2e\x61\x70\x70\x65\x6e\x64\x65\x72\x2e\x73\x74\x64\x6f\x75\x74\x2e\x54\x68\x72\x65\x73\x68\x6f\x6c\x64\x3d\x4f\x46\x46\x22\x20\x3e\x3e\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6c\x6f\x67\x34\x6a\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x0a\x20\x20\x23\x20\x66\x6f\x72\x6d\x61\x74\x20\x74\x68\x65\x20\x64\x61\x74\x61\x20\x70\x61\x74\x68\x0a\x20\x20\x6d\x75\x73\x74\x5f\x64\x6f\x20\x2d\x76\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x62\x69\x6e\x2f\x6b\x61\x66\x6b\x61\x2d\x73\x74\x6f\x72\x61\x67\x65\x2e\x73\x68\x20\x66\x6f\x72\x6d\x61\x74\x20\x2d\x67\x20\x2d\x74\x20\x24\x7b\x63\x6c\x75\x73\x74\x65\x72\x5f\x69\x64\x7d\x20\x2d\x63\x20\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x0a\x20\x20\x65\x78\x65\x63\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x62\x69\x6e\x2f\x6b\x61\x66\x6b\x61\x2d\x73\x65\x72\x76\x65\x72\x2d\x73\x74\x61\x72\x74\x2e\x73\x68\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x7d\x0a\x0a\x23\x20\x50\x61\x72\x73\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x2d\x6c\x69\x6e\x65\x20\x61\x72\x67\x75\x6d\x65\x6e\x74\x73\x0a\x5b\x5b\x20\x24\x23\x20\x2d\x6c\x74\x20\x31\x20\x5d\x5d\x20\x26\x26\x20\x75\x73\x61\x67\x65\x20\x30\x0a\x23\x20\x44\x69\x73\x70\x6c\x61\x79\x20\x74\x68\x65\x20\x68\x65\x6c\x70\x20\x74\x65\x78\x74\x20\x69\x66\x20\x2d\x68\x20\x6f\x72\x20\x2d\x2d\x68\x65\x6c\x70\x20\x61\x70\x70\x65\x61\x72\x73\x20\x69\x6e\x20\x74\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x6c\x69\x6e\x65\x0a\x66\x6f\x72\x20\x61\x72\x67\x20\x69\x6e\x20\x22\x24\x7b\x40\x7d\x22\x3b\x20\x64\x6f\x0a\x20\x20\x63\x61\x73\x65\x20\x22\x24\x7b\x61\x72\x67\x7d\x22\x20\x69\x6e\x0a\x20\x20\x2d\x68\x20\x7c\x20\x2d\x2d\x68\x65\x6c\x70\x29\x20\x75\x73\x61\x67\x65\x20\x30\x20\x3b\x3b\x0a\x20\x20\x2d\x2d\x29\x20\x62\x72\x65\x61\x6b\x20\x3b\x3b\x0a\x20\x20\x2a\x29\x20\x3b\x3b\x0a\x20\x20\x65\x73\x61\x63\x0a\x64\x6f\x6e\x65\x0a\x61\x63\x74\x69\x6f\x6e\x3d\x22\x24\x7b\x31\x7d\x22\x0a\x73\x68\x69\x66\x74\x0a\x63\x61\x73\x65\x20\x22\x24\x7b\x61\x63\x74\x69\x6f\x6e\x7d\x22\x20\x69\x6e\x0a\x68\x65\x6c\x70\x29\x20\x75\x73\x61\x67\x65\x20\x30\x20\x3b\x3b\x0a\x0a\x75\x70\x29\x0a\x20\x20\x6b\x61\x66\x6b\x61\x5f\x22\x24\x7b\x61\x63\x74\x69\x6f\x6e\x7d\x22\x20\x22\x24\x7b\x40\x7d\x22\x0a\x20\x20\x65\x78\x69\x74\x20\x30\x0a\x20\x20\x3b\x3b\x0a\x0a\x2a\x29\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x27\x24\x7b\x61\x63\x74\x69\x6f\x6e\x7d\x27\x2e\x20\x20\x54\x79\x70\x65\x20\x27\x24\x7b\x73\x63\x72\x69\x70\x74\x5f\x70\x61\x74\x68\x7d\x20\x2d\x2d\x68\x65\x6c\x70\x27\x20\x66\x6f\x72\x20\x75\x73\x61\x67\x65\x20\x69\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\x2e\x22\x0a\x20\x20\x65\x78\x69\x74\x20\x31\x0a\x20\x20\x3b\x3b\x0a\x65\x73\x61\x63\x0a" +var _defaultsUpSh = "\x23\x21\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x65\x6e\x76\x20\x62\x61\x73\x68\x0a\x0a\x23\x20\x4c\x69\x63\x65\x6e\x73\x65\x64\x20\x74\x6f\x20\x74\x68\x65\x20\x41\x70\x61\x63\x68\x65\x20\x53\x6f\x66\x74\x77\x61\x72\x65\x20\x46\x6f\x75\x6e\x64\x61\x74\x69\x6f\x6e\x20\x28\x41\x53\x46\x29\x20\x75\x6e\x64\x65\x72\x20\x6f\x6e\x65\x20\x6f\x72\x20\x6d\x6f\x72\x65\x0a\x23\x20\x63\x6f\x6e\x74\x72\x69\x62\x75\x74\x6f\x72\x20\x6c\x69\x63\x65\x6e\x73\x65\x20\x61\x67\x72\x65\x65\x6d\x65\x6e\x74\x73\x2e\x20\x20\x53\x65\x65\x20\x74\x68\x65\x20\x4e\x4f\x54\x49\x43\x45\x20\x66\x69\x6c\x65\x20\x64\x69\x73\x74\x72\x69\x62\x75\x74\x65\x64\x20\x77\x69\x74\x68\x0a\x23\x20\x74\x68\x69\x73\x20\x77\x6f\x72\x6b\x20\x66\x6f\x72\x20\x61\x64\x64\x69\x74\x69\x6f\x6e\x61\x6c\x20\x69\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\x20\x72\x65\x67\x61\x72\x64\x69\x6e\x67\x20\x63\x6f\x70\x79\x72\x69\x67\x68\x74\x20\x6f\x77\x6e\x65\x72\x73\x68\x69\x70\x2e\x0a\x23\x20\x54\x68\x65\x20\x41\x53\x46\x20\x6c\x69\x63\x65\x6e\x73\x65\x73\x20\x74\x68\x69\x73\x20\x66\x69\x6c\x65\x20\x74\x6f\x20\x59\x6f\x75\x20\x75\x6e\x64\x65\x72\x20\x74\x68\x65\x20\x41\x70\x61\x63\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x2c\x20\x56\x65\x72\x73\x69\x6f\x6e\x20\x32\x2e\x30\x0a\x23\x20\x28\x74\x68\x65\x20\x22\x4c\x69\x63\x65\x6e\x73\x65\x22\x29\x3b\x20\x79\x6f\x75\x20\x6d\x61\x79\x20\x6e\x6f\x74\x20\x75\x73\x65\x20\x74\x68\x69\x73\x20\x66\x69\x6c\x65\x20\x65\x78\x63\x65\x70\x74\x20\x69\x6e\x20\x63\x6f\x6d\x70\x6c\x69\x61\x6e\x63\x65\x20\x77\x69\x74\x68\x0a\x23\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x2e\x20\x20\x59\x6f\x75\x20\x6d\x61\x79\x20\x6f\x62\x74\x61\x69\x6e\x20\x61\x20\x63\x6f\x70\x79\x20\x6f\x66\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x20\x61\x74\x0a\x23\x0a\x23\x20\x20\x20\x20\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x61\x70\x61\x63\x68\x65\x2e\x6f\x72\x67\x2f\x6c\x69\x63\x65\x6e\x73\x65\x73\x2f\x4c\x49\x43\x45\x4e\x53\x45\x2d\x32\x2e\x30\x0a\x23\x0a\x23\x20\x55\x6e\x6c\x65\x73\x73\x20\x72\x65\x71\x75\x69\x72\x65\x64\x20\x62\x79\x20\x61\x70\x70\x6c\x69\x63\x61\x62\x6c\x65\x20\x6c\x61\x77\x20\x6f\x72\x20\x61\x67\x72\x65\x65\x64\x20\x74\x6f\x20\x69\x6e\x20\x77\x72\x69\x74\x69\x6e\x67\x2c\x20\x73\x6f\x66\x74\x77\x61\x72\x65\x0a\x23\x20\x64\x69\x73\x74\x72\x69\x62\x75\x74\x65\x64\x20\x75\x6e\x64\x65\x72\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x20\x69\x73\x20\x64\x69\x73\x74\x72\x69\x62\x75\x74\x65\x64\x20\x6f\x6e\x20\x61\x6e\x20\x22\x41\x53\x20\x49\x53\x22\x20\x42\x41\x53\x49\x53\x2c\x0a\x23\x20\x57\x49\x54\x48\x4f\x55\x54\x20\x57\x41\x52\x52\x41\x4e\x54\x49\x45\x53\x20\x4f\x52\x20\x43\x4f\x4e\x44\x49\x54\x49\x4f\x4e\x53\x20\x4f\x46\x20\x41\x4e\x59\x20\x4b\x49\x4e\x44\x2c\x20\x65\x69\x74\x68\x65\x72\x20\x65\x78\x70\x72\x65\x73\x73\x20\x6f\x72\x20\x69\x6d\x70\x6c\x69\x65\x64\x2e\x0a\x23\x20\x53\x65\x65\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x73\x70\x65\x63\x69\x66\x69\x63\x20\x6c\x61\x6e\x67\x75\x61\x67\x65\x20\x67\x6f\x76\x65\x72\x6e\x69\x6e\x67\x20\x70\x65\x72\x6d\x69\x73\x73\x69\x6f\x6e\x73\x20\x61\x6e\x64\x0a\x23\x20\x6c\x69\x6d\x69\x74\x61\x74\x69\x6f\x6e\x73\x20\x75\x6e\x64\x65\x72\x20\x74\x68\x65\x20\x4c\x69\x63\x65\x6e\x73\x65\x2e\x0a\x0a\x73\x63\x72\x69\x70\x74\x5f\x70\x61\x74\x68\x3d\x22\x24\x7b\x30\x7d\x22\x0a\x0a\x23\x20\x54\x68\x65\x20\x61\x62\x73\x6f\x6c\x75\x74\x65\x20\x70\x61\x74\x68\x20\x74\x6f\x20\x74\x68\x65\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x20\x77\x68\x69\x63\x68\x20\x74\x68\x69\x73\x20\x73\x63\x72\x69\x70\x74\x20\x69\x73\x20\x69\x6e\x2e\x0a\x73\x74\x61\x72\x74\x5f\x64\x69\x72\x3d\x22\x24\x28\x63\x64\x20\x22\x24\x28\x64\x69\x72\x6e\x61\x6d\x65\x20\x22\x24\x7b\x42\x41\x53\x48\x5f\x53\x4f\x55\x52\x43\x45\x5b\x30\x5d\x7d\x22\x29\x22\x20\x26\x26\x20\x70\x77\x64\x29\x22\x0a\x0a\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x3d\x22\x24\x7b\x73\x74\x61\x72\x74\x5f\x64\x69\x72\x7d\x2f\x72\x75\x6e\x2e\x69\x6e\x66\x6f\x22\x0a\x0a\x23\x20\x54\x68\x65\x20\x61\x62\x73\x6f\x6c\x75\x74\x65\x20\x70\x61\x74\x68\x20\x74\x6f\x20\x74\x68\x65\x20\x72\x6f\x6f\x74\x20\x4b\x61\x66\x6b\x61\x20\x64\x69\x72\x65\x63\x74\x6f\x72\x79\x0a\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x3d\x22\x24\x28\x20\x63\x64\x20\x22\x24\x7b\x73\x74\x61\x72\x74\x5f\x64\x69\x72\x7d\x2f\x2e\x2e\x2f\x6b\x61\x66\x6b\x61\x22\x20\x26\x26\x20\x70\x77\x64\x20\x29\x22\x0a\x0a\x64\x61\x74\x61\x5f\x70\x61\x74\x68\x3d\x22\x2f\x64\x61\x74\x61\x2f\x6b\x61\x66\x6b\x61\x22\x0a\x0a\x23\x20\x45\x78\x69\x74\x20\x77\x69\x74\x68\x20\x61\x6e\x20\x65\x72\x72\x6f\x72\x20\x6d\x65\x73\x73\x61\x67\x65\x2e\x0a\x64\x69\x65\x28\x29\x20\x7b\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x24\x40\x22\x0a\x20\x20\x65\x78\x69\x74\x20\x31\x0a\x7d\x0a\x0a\x65\x63\x68\x6f\x5f\x61\x6e\x64\x5f\x64\x6f\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x63\x6d\x64\x3d\x22\x24\x7b\x40\x7d\x22\x0a\x20\x20\x20\x20\x65\x63\x68\x6f\x20\x22\x24\x7b\x63\x6d\x64\x7d\x22\x0a\x20\x20\x20\x20\x24\x7b\x63\x6d\x64\x7d\x0a\x7d\x0a\x0a\x23\x20\x52\x75\x6e\x20\x61\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x61\x6e\x64\x20\x64\x69\x65\x20\x69\x66\x20\x69\x74\x20\x66\x61\x69\x6c\x73\x2e\x0a\x23\x0a\x23\x20\x4f\x70\x74\x69\x6f\x6e\x61\x6c\x20\x66\x6c\x61\x67\x73\x3a\x0a\x23\x20\x2d\x76\x3a\x20\x70\x72\x69\x6e\x74\x20\x74\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x62\x65\x66\x6f\x72\x65\x20\x72\x75\x6e\x6e\x69\x6e\x67\x20\x69\x74\x2e\x0a\x23\x20\x2d\x6f\x3a\x20\x64\x69\x73\x70\x6c\x61\x79\x20\x74\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x6f\x75\x74\x70\x75\x74\x2e\x0a\x23\x20\x24\x40\x3a\x20\x54\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x74\x6f\x20\x72\x75\x6e\x2e\x0a\x6d\x75\x73\x74\x5f\x64\x6f\x28\x29\x20\x7b\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x76\x65\x72\x62\x6f\x73\x65\x3d\x30\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x6f\x75\x74\x70\x75\x74\x3d\x22\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x22\x0a\x20\x20\x77\x68\x69\x6c\x65\x20\x74\x72\x75\x65\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x63\x61\x73\x65\x20\x24\x7b\x31\x7d\x20\x69\x6e\x0a\x20\x20\x20\x20\x2d\x76\x29\x0a\x20\x20\x20\x20\x20\x20\x76\x65\x72\x62\x6f\x73\x65\x3d\x31\x0a\x20\x20\x20\x20\x20\x20\x73\x68\x69\x66\x74\x0a\x20\x20\x20\x20\x20\x20\x3b\x3b\x0a\x20\x20\x20\x20\x2d\x6f\x29\x0a\x20\x20\x20\x20\x20\x20\x6f\x75\x74\x70\x75\x74\x3d\x22\x2f\x64\x65\x76\x2f\x73\x74\x64\x6f\x75\x74\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x68\x69\x66\x74\x0a\x20\x20\x20\x20\x20\x20\x3b\x3b\x0a\x20\x20\x20\x20\x2a\x29\x20\x62\x72\x65\x61\x6b\x20\x3b\x3b\x0a\x20\x20\x20\x20\x65\x73\x61\x63\x0a\x20\x20\x64\x6f\x6e\x65\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x63\x6d\x64\x3d\x22\x24\x2a\x22\x0a\x20\x20\x5b\x5b\x20\x22\x24\x7b\x76\x65\x72\x62\x6f\x73\x65\x7d\x22\x20\x2d\x65\x71\x20\x31\x20\x5d\x5d\x20\x26\x26\x20\x65\x63\x68\x6f\x20\x22\x24\x7b\x63\x6d\x64\x7d\x22\x0a\x20\x20\x65\x76\x61\x6c\x20\x22\x24\x7b\x63\x6d\x64\x7d\x22\x20\x3e\x24\x7b\x6f\x75\x74\x70\x75\x74\x7d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x24\x7b\x31\x7d\x20\x66\x61\x69\x6c\x65\x64\x22\x0a\x7d\x0a\x0a\x23\x20\x44\x69\x73\x70\x6c\x61\x79\x20\x61\x20\x75\x73\x61\x67\x65\x20\x6d\x65\x73\x73\x61\x67\x65\x20\x6f\x6e\x20\x74\x68\x65\x20\x74\x65\x72\x6d\x69\x6e\x61\x6c\x20\x61\x6e\x64\x20\x65\x78\x69\x74\x2e\x0a\x23\x0a\x23\x20\x24\x31\x3a\x20\x54\x68\x65\x20\x65\x78\x69\x74\x20\x73\x74\x61\x74\x75\x73\x20\x74\x6f\x20\x75\x73\x65\x0a\x75\x73\x61\x67\x65\x28\x29\x20\x7b\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x65\x78\x69\x74\x5f\x73\x74\x61\x74\x75\x73\x3d\x22\x24\x7b\x31\x7d\x22\x0a\x20\x20\x63\x61\x74\x20\x3c\x3c\x45\x4f\x46\x0a\x73\x74\x61\x72\x74\x3a\x20\x61\x20\x74\x6f\x6f\x6c\x20\x66\x6f\x72\x20\x73\x74\x61\x72\x74\x69\x6e\x67\x20\x27\x41\x75\x74\x6f\x4d\x51\x20\x66\x6f\x72\x20\x41\x70\x61\x63\x68\x65\x20\x4b\x61\x66\x6b\x61\x20\x6f\x6e\x20\x53\x33\x27\x2e\x0a\x0a\x55\x73\x61\x67\x65\x3a\x20\x24\x7b\x73\x63\x72\x69\x70\x74\x5f\x70\x61\x74\x68\x7d\x20\x5b\x63\x6f\x6d\x6d\x61\x6e\x64\x5d\x20\x5b\x6f\x70\x74\x69\x6f\x6e\x73\x5d\x0a\x0a\x68\x65\x6c\x70\x7c\x2d\x68\x7c\x2d\x2d\x68\x65\x6c\x70\x0a\x20\x20\x20\x20\x44\x69\x73\x70\x6c\x61\x79\x20\x74\x68\x69\x73\x20\x68\x65\x6c\x70\x20\x6d\x65\x73\x73\x61\x67\x65\x0a\x75\x70\x20\x5b\x2d\x2d\x70\x72\x6f\x63\x65\x73\x73\x2e\x72\x6f\x6c\x65\x73\x20\x52\x4f\x4c\x45\x5d\x20\x5b\x2d\x2d\x6e\x6f\x64\x65\x2e\x69\x64\x20\x4e\x4f\x44\x45\x5f\x49\x44\x5d\x20\x5b\x2d\x2d\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x71\x75\x6f\x72\x75\x6d\x2e\x76\x6f\x74\x65\x72\x73\x20\x56\x4f\x54\x45\x52\x53\x5d\x0a\x20\x20\x20\x5b\x2d\x2d\x73\x33\x2e\x72\x65\x67\x69\x6f\x6e\x20\x52\x45\x47\x49\x4f\x4e\x5d\x20\x5b\x2d\x2d\x73\x33\x2e\x62\x75\x63\x6b\x65\x74\x20\x42\x55\x43\x4b\x45\x54\x5d\x20\x5b\x2d\x2d\x73\x33\x2e\x65\x6e\x64\x70\x6f\x69\x6e\x74\x20\x45\x4e\x44\x50\x4f\x49\x4e\x54\x5d\x0a\x20\x20\x20\x5b\x2d\x2d\x73\x33\x2e\x61\x63\x63\x65\x73\x73\x2e\x6b\x65\x79\x20\x41\x43\x43\x45\x53\x53\x5f\x4b\x45\x59\x5d\x20\x5b\x2d\x2d\x73\x33\x2e\x73\x65\x63\x72\x65\x74\x2e\x6b\x65\x79\x20\x53\x45\x43\x52\x45\x54\x5f\x4b\x45\x59\x5d\x0a\x20\x20\x20\x20\x73\x74\x61\x72\x74\x20\x6e\x6f\x64\x65\x2e\x0a\x45\x4f\x46\x0a\x20\x20\x65\x78\x69\x74\x20\x22\x24\x7b\x65\x78\x69\x74\x5f\x73\x74\x61\x74\x75\x73\x7d\x22\x0a\x7d\x0a\x0a\x23\x20\x43\x68\x65\x63\x6b\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x70\x72\x65\x73\x65\x6e\x63\x65\x20\x6f\x66\x20\x63\x65\x72\x74\x61\x69\x6e\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x2e\x0a\x23\x0a\x23\x20\x24\x40\x3a\x20\x54\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x20\x74\x6f\x20\x63\x68\x65\x63\x6b\x20\x66\x6f\x72\x2e\x20\x20\x54\x68\x69\x73\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x20\x77\x69\x6c\x6c\x20\x64\x69\x65\x20\x69\x66\x20\x61\x6e\x79\x20\x6f\x66\x20\x74\x68\x65\x73\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x20\x61\x72\x65\x20\x6e\x6f\x74\x20\x66\x6f\x75\x6e\x64\x20\x62\x79\x0a\x23\x20\x20\x20\x20\x20\x20\x20\x74\x68\x65\x20\x27\x77\x68\x69\x63\x68\x27\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x2e\x0a\x72\x65\x71\x75\x69\x72\x65\x5f\x63\x6f\x6d\x6d\x61\x6e\x64\x73\x28\x29\x20\x7b\x0a\x20\x20\x6c\x6f\x63\x61\x6c\x20\x63\x6d\x64\x73\x3d\x28\x22\x24\x40\x22\x29\x0a\x20\x20\x66\x6f\x72\x20\x63\x6d\x64\x20\x69\x6e\x20\x22\x24\x7b\x63\x6d\x64\x73\x5b\x40\x5d\x7d\x22\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x77\x68\x69\x63\x68\x20\x2d\x2d\x20\x22\x24\x7b\x63\x6d\x64\x7d\x22\x20\x26\x3e\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x59\x6f\x75\x20\x6d\x75\x73\x74\x20\x69\x6e\x73\x74\x61\x6c\x6c\x20\x24\x7b\x63\x6d\x64\x7d\x20\x74\x6f\x20\x72\x75\x6e\x20\x74\x68\x69\x73\x20\x73\x63\x72\x69\x70\x74\x2e\x22\x0a\x20\x20\x64\x6f\x6e\x65\x0a\x7d\x0a\x0a\x23\x20\x53\x65\x74\x20\x61\x20\x67\x6c\x6f\x62\x61\x6c\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x74\x6f\x20\x61\x20\x76\x61\x6c\x75\x65\x2e\x0a\x23\x0a\x23\x20\x24\x31\x3a\x20\x54\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x6e\x61\x6d\x65\x20\x74\x6f\x20\x73\x65\x74\x2e\x20\x20\x54\x68\x69\x73\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x20\x77\x69\x6c\x6c\x20\x64\x69\x65\x20\x69\x66\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x68\x61\x73\x20\x61\x20\x76\x61\x6c\x75\x65\x2e\x20\x20\x54\x68\x65\x0a\x23\x20\x20\x20\x20\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x77\x69\x6c\x6c\x20\x62\x65\x20\x6d\x61\x64\x65\x20\x72\x65\x61\x64\x6f\x6e\x6c\x79\x20\x74\x6f\x20\x70\x72\x65\x76\x65\x6e\x74\x20\x61\x6e\x79\x20\x66\x75\x74\x75\x72\x65\x20\x6d\x6f\x64\x69\x66\x69\x63\x61\x74\x69\x6f\x6e\x73\x2e\x0a\x23\x20\x24\x32\x3a\x20\x54\x68\x65\x20\x76\x61\x6c\x75\x65\x20\x74\x6f\x20\x73\x65\x74\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x20\x74\x6f\x2e\x20\x20\x54\x68\x69\x73\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x20\x77\x69\x6c\x6c\x20\x64\x69\x65\x20\x69\x66\x20\x74\x68\x65\x20\x76\x61\x6c\x75\x65\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x20\x6f\x72\x20\x73\x74\x61\x72\x74\x73\x0a\x23\x20\x20\x20\x20\x20\x77\x69\x74\x68\x20\x61\x20\x64\x61\x73\x68\x2e\x0a\x23\x20\x24\x33\x3a\x20\x41\x20\x68\x75\x6d\x61\x6e\x2d\x72\x65\x61\x64\x61\x62\x6c\x65\x20\x64\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x6f\x66\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x2e\x0a\x73\x65\x74\x5f\x6f\x6e\x63\x65\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x6b\x65\x79\x3d\x22\x24\x7b\x31\x7d\x22\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x76\x61\x6c\x75\x65\x3d\x22\x24\x7b\x32\x7d\x22\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x77\x68\x61\x74\x3d\x22\x24\x7b\x33\x7d\x22\x0a\x20\x20\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x21\x6b\x65\x79\x7d\x22\x20\x5d\x5d\x20\x26\x26\x20\x64\x69\x65\x20\x22\x45\x72\x72\x6f\x72\x3a\x20\x6d\x6f\x72\x65\x20\x74\x68\x61\x6e\x20\x6f\x6e\x65\x20\x76\x61\x6c\x75\x65\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64\x20\x66\x6f\x72\x20\x24\x7b\x77\x68\x61\x74\x7d\x2e\x22\x0a\x20\x20\x20\x20\x76\x65\x72\x69\x66\x79\x5f\x63\x6f\x6d\x6d\x61\x6e\x64\x5f\x6c\x69\x6e\x65\x5f\x61\x72\x67\x75\x6d\x65\x6e\x74\x20\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x22\x24\x7b\x77\x68\x61\x74\x7d\x22\x0a\x20\x20\x20\x20\x23\x20\x49\x74\x20\x77\x6f\x75\x6c\x64\x20\x62\x65\x20\x62\x65\x74\x74\x65\x72\x20\x74\x6f\x20\x75\x73\x65\x20\x64\x65\x63\x6c\x61\x72\x65\x20\x2d\x67\x2c\x20\x62\x75\x74\x20\x6f\x6c\x64\x65\x72\x20\x62\x61\x73\x68\x20\x76\x65\x72\x73\x69\x6f\x6e\x73\x20\x64\x6f\x6e\x27\x74\x20\x73\x75\x70\x70\x6f\x72\x74\x20\x69\x74\x2e\x0a\x20\x20\x20\x20\x65\x78\x70\x6f\x72\x74\x20\x22\x24\x7b\x6b\x65\x79\x7d\x22\x3d\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x0a\x7d\x0a\x0a\x23\x20\x56\x65\x72\x69\x66\x79\x20\x74\x68\x61\x74\x20\x61\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x2d\x6c\x69\x6e\x65\x20\x61\x72\x67\x75\x6d\x65\x6e\x74\x20\x69\x73\x20\x70\x72\x65\x73\x65\x6e\x74\x20\x61\x6e\x64\x20\x64\x6f\x65\x73\x20\x6e\x6f\x74\x20\x73\x74\x61\x72\x74\x20\x77\x69\x74\x68\x20\x61\x20\x73\x6c\x61\x73\x68\x2e\x0a\x23\x0a\x23\x20\x24\x31\x3a\x20\x54\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x2d\x6c\x69\x6e\x65\x20\x61\x72\x67\x75\x6d\x65\x6e\x74\x20\x74\x6f\x20\x76\x65\x72\x69\x66\x79\x2e\x0a\x23\x20\x24\x32\x3a\x20\x41\x20\x68\x75\x6d\x61\x6e\x2d\x72\x65\x61\x64\x61\x62\x6c\x65\x20\x64\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20\x6f\x66\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x2e\x0a\x76\x65\x72\x69\x66\x79\x5f\x63\x6f\x6d\x6d\x61\x6e\x64\x5f\x6c\x69\x6e\x65\x5f\x61\x72\x67\x75\x6d\x65\x6e\x74\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x76\x61\x6c\x75\x65\x3d\x22\x24\x7b\x31\x7d\x22\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x77\x68\x61\x74\x3d\x22\x24\x7b\x32\x7d\x22\x0a\x20\x20\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x45\x72\x72\x6f\x72\x3a\x20\x6e\x6f\x20\x76\x61\x6c\x75\x65\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64\x20\x66\x6f\x72\x20\x24\x7b\x77\x68\x61\x74\x7d\x22\x0a\x20\x20\x20\x20\x5b\x5b\x20\x24\x7b\x76\x61\x6c\x75\x65\x7d\x20\x3d\x3d\x20\x2d\x2a\x20\x5d\x5d\x20\x26\x26\x20\x64\x69\x65\x20\x22\x45\x72\x72\x6f\x72\x3a\x20\x69\x6e\x76\x61\x6c\x69\x64\x20\x76\x61\x6c\x75\x65\x20\x24\x7b\x76\x61\x6c\x75\x65\x7d\x20\x73\x70\x65\x63\x69\x66\x69\x65\x64\x20\x66\x6f\x72\x20\x24\x7b\x77\x68\x61\x74\x7d\x22\x0a\x7d\x0a\x0a\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x28\x29\x20\x7b\x0a\x20\x20\x6b\x65\x79\x3d\x24\x31\x0a\x20\x20\x76\x61\x6c\x75\x65\x3d\x24\x32\x0a\x20\x20\x66\x69\x6c\x65\x3d\x24\x33\x0a\x20\x20\x23\x20\x72\x65\x70\x6c\x61\x63\x65\x20\x73\x70\x65\x63\x69\x61\x6c\x20\x63\x68\x61\x72\x61\x63\x74\x65\x72\x73\x0a\x20\x20\x76\x61\x6c\x75\x65\x3d\x24\x7b\x76\x61\x6c\x75\x65\x2f\x2f\x26\x2f\x5c\x5c\x26\x7d\x0a\x20\x20\x76\x61\x6c\x75\x65\x3d\x24\x7b\x76\x61\x6c\x75\x65\x2f\x2f\x23\x2f\x2f\x5c\x5c\x23\x2f\x7d\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x3a\x20\x6b\x65\x79\x3d\x24\x7b\x6b\x65\x79\x7d\x2c\x20\x76\x61\x6c\x75\x65\x3d\x24\x7b\x76\x61\x6c\x75\x65\x7d\x2c\x20\x66\x69\x6c\x65\x3d\x24\x7b\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x73\x65\x64\x20\x2d\x69\x20\x22\x73\x7c\x5e\x24\x7b\x6b\x65\x79\x7d\x3d\x2e\x2a\x24\x7c\x24\x7b\x6b\x65\x79\x7d\x3d\x24\x7b\x76\x61\x6c\x75\x65\x7d\x7c\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x7d\x22\x0a\x7d\x0a\x0a\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x28\x29\x20\x7b\x0a\x20\x20\x6b\x65\x79\x3d\x24\x31\x0a\x20\x20\x76\x61\x6c\x75\x65\x3d\x24\x32\x0a\x20\x20\x66\x69\x6c\x65\x3d\x24\x33\x0a\x20\x20\x69\x66\x20\x67\x72\x65\x70\x20\x2d\x71\x20\x22\x5e\x24\x7b\x6b\x65\x79\x7d\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x7d\x22\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x24\x7b\x6b\x65\x79\x7d\x22\x20\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x65\x6c\x73\x65\x0a\x20\x20\x20\x20\x65\x63\x68\x6f\x20\x22\x24\x7b\x6b\x65\x79\x7d\x3d\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x7c\x20\x74\x65\x65\x20\x2d\x61\x20\x22\x24\x7b\x66\x69\x6c\x65\x7d\x22\x20\x3e\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c\x0a\x20\x20\x66\x69\x0a\x7d\x0a\x0a\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x61\x6c\x6c\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x74\x6f\x70\x69\x63\x22\x20\x22\x41\x75\x74\x6f\x42\x61\x6c\x61\x6e\x63\x65\x72\x4d\x65\x74\x72\x69\x63\x73\x52\x65\x70\x6f\x72\x74\x65\x72\x54\x6f\x70\x69\x63\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x74\x6f\x70\x69\x63\x2e\x6e\x75\x6d\x2e\x70\x61\x72\x74\x69\x74\x69\x6f\x6e\x73\x22\x20\x22\x31\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x7d\x0a\x0a\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x5f\x6f\x6e\x6c\x79\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x65\x6e\x61\x62\x6c\x65\x22\x20\x22\x74\x72\x75\x65\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x65\x78\x63\x6c\x75\x64\x65\x2e\x74\x6f\x70\x69\x63\x73\x22\x20\x22\x5f\x5f\x63\x6f\x6e\x73\x75\x6d\x65\x72\x5f\x6f\x66\x66\x73\x65\x74\x73\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x7d\x0a\x0a\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x62\x72\x6f\x6b\x65\x72\x5f\x6f\x6e\x6c\x79\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6d\x65\x74\x72\x69\x63\x2e\x72\x65\x70\x6f\x72\x74\x65\x72\x73\x22\x20\x22\x6b\x61\x66\x6b\x61\x2e\x61\x75\x74\x6f\x62\x61\x6c\x61\x6e\x63\x65\x72\x2e\x6d\x65\x74\x72\x69\x63\x73\x72\x65\x70\x6f\x72\x74\x65\x72\x2e\x41\x75\x74\x6f\x42\x61\x6c\x61\x6e\x63\x65\x72\x4d\x65\x74\x72\x69\x63\x73\x52\x65\x70\x6f\x72\x74\x65\x72\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x7d\x0a\x0a\x74\x75\x72\x6e\x5f\x6f\x6e\x5f\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x72\x6f\x6c\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x32\x0a\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x61\x6c\x6c\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x62\x72\x6f\x6b\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x62\x72\x6f\x6b\x65\x72\x5f\x6f\x6e\x6c\x79\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x5f\x6f\x6e\x6c\x79\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x73\x65\x72\x76\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x5f\x6f\x6e\x6c\x79\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x5f\x73\x65\x74\x74\x69\x6e\x67\x5f\x66\x6f\x72\x5f\x62\x72\x6f\x6b\x65\x72\x5f\x6f\x6e\x6c\x79\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x66\x69\x0a\x7d\x0a\x0a\x0a\x23\x20\x6d\x6f\x6e\x69\x74\x6f\x72\x20\x61\x6e\x64\x20\x63\x68\x61\x6e\x67\x65\x20\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x20\x69\x70\x20\x66\x6f\x72\x20\x6b\x61\x66\x6b\x61\x0a\x6b\x61\x66\x6b\x61\x5f\x6d\x6f\x6e\x69\x74\x6f\x72\x5f\x69\x70\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x3d\x24\x28\x67\x72\x65\x70\x20\x22\x72\x6f\x6c\x65\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x20\x7c\x20\x61\x77\x6b\x20\x2d\x46\x3d\x20\x27\x7b\x70\x72\x69\x6e\x74\x20\x24\x32\x7d\x27\x29\x0a\x20\x20\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x6b\x61\x66\x6b\x61\x5f\x64\x6f\x77\x6e\x3a\x20\x66\x61\x69\x6c\x65\x64\x20\x74\x6f\x20\x67\x65\x74\x20\x6e\x6f\x64\x65\x20\x72\x6f\x6c\x65\x22\x0a\x0a\x20\x20\x20\x20\x23\x20\x67\x65\x74\x20\x70\x72\x69\x76\x61\x74\x65\x20\x69\x70\x20\x66\x69\x72\x73\x74\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x3d\x22\x30\x2e\x30\x2e\x30\x2e\x30\x22\x0a\x20\x20\x20\x20\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x5f\x69\x70\x5f\x70\x6f\x72\x74\x3d\x22\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x32\x22\x0a\x20\x20\x20\x20\x69\x66\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x4f\x50\x45\x52\x41\x54\x4f\x52\x5f\x41\x50\x49\x53\x5f\x41\x44\x44\x52\x7d\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6e\x6f\x64\x65\x5f\x69\x70\x3d\x24\x28\x63\x75\x72\x6c\x20\x2d\x66\x20\x2d\x73\x20\x22\x24\x7b\x4f\x50\x45\x52\x41\x54\x4f\x52\x5f\x41\x50\x49\x53\x5f\x41\x44\x44\x52\x7d\x3a\x2f\x61\x70\x69\x2f\x76\x31\x2f\x6e\x6f\x64\x65\x73\x2f\x24\x7b\x4e\x4f\x44\x45\x5f\x4e\x41\x4d\x45\x7d\x22\x29\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x69\x66\x20\x5b\x5b\x20\x24\x3f\x20\x2d\x65\x71\x20\x30\x20\x26\x26\x20\x2d\x6e\x20\x22\x24\x6e\x6f\x64\x65\x5f\x69\x70\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x5f\x69\x70\x5f\x70\x6f\x72\x74\x3d\x22\x24\x7b\x6e\x6f\x64\x65\x5f\x69\x70\x7d\x3a\x24\x7b\x4e\x4f\x44\x45\x50\x4f\x52\x54\x5f\x44\x45\x46\x41\x55\x4c\x54\x5f\x50\x4f\x52\x54\x7d\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x65\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x63\x68\x6f\x20\x22\x46\x61\x69\x6c\x65\x64\x20\x74\x6f\x20\x72\x65\x74\x72\x69\x65\x76\x65\x20\x6e\x6f\x64\x65\x5f\x69\x70\x20\x66\x72\x6f\x6d\x20\x24\x7b\x4f\x50\x45\x52\x41\x54\x4f\x52\x5f\x41\x50\x49\x53\x5f\x41\x44\x44\x52\x7d\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x65\x78\x69\x74\x20\x31\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x69\x0a\x20\x20\x20\x20\x66\x69\x0a\x0a\x0a\x20\x20\x20\x20\x23\x20\x63\x68\x61\x6e\x67\x65\x20\x69\x70\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x66\x6f\x72\x20\x74\x68\x69\x73\x20\x6e\x6f\x64\x65\x0a\x20\x20\x20\x20\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x73\x65\x72\x76\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x50\x4c\x41\x49\x4e\x54\x45\x58\x54\x3a\x2f\x2f\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x32\x2c\x43\x4f\x4e\x54\x52\x4f\x4c\x4c\x45\x52\x3a\x2f\x2f\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x33\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x2e\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x50\x4c\x41\x49\x4e\x54\x45\x58\x54\x3a\x2f\x2f\x24\x7b\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x5f\x69\x70\x5f\x70\x6f\x72\x74\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x62\x72\x6f\x6b\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x50\x4c\x41\x49\x4e\x54\x45\x58\x54\x3a\x2f\x2f\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x32\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x2e\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x50\x4c\x41\x49\x4e\x54\x45\x58\x54\x3a\x2f\x2f\x24\x7b\x61\x64\x76\x65\x72\x74\x69\x73\x65\x64\x5f\x69\x70\x5f\x70\x6f\x72\x74\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6c\x69\x73\x74\x65\x6e\x65\x72\x73\x22\x20\x22\x43\x4f\x4e\x54\x52\x4f\x4c\x4c\x45\x52\x3a\x2f\x2f\x24\x7b\x6c\x6f\x63\x61\x6c\x5f\x70\x72\x69\x76\x61\x74\x65\x5f\x69\x70\x7d\x3a\x39\x30\x39\x33\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x65\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x64\x69\x65\x20\x22\x6b\x61\x66\x6b\x61\x5f\x6d\x6f\x6e\x69\x74\x6f\x72\x5f\x69\x70\x3a\x20\x75\x6e\x6b\x6e\x6f\x77\x6e\x20\x70\x72\x6f\x63\x65\x73\x73\x20\x72\x6f\x6c\x65\x20\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x0a\x20\x20\x20\x20\x66\x69\x0a\x7d\x0a\x0a\x63\x6f\x6e\x66\x69\x67\x75\x72\x65\x5f\x66\x72\x6f\x6d\x5f\x65\x6e\x76\x69\x72\x6f\x6e\x6d\x65\x6e\x74\x5f\x76\x61\x72\x69\x61\x62\x6c\x65\x73\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x3d\x24\x31\x0a\x20\x20\x20\x20\x23\x20\x4c\x69\x73\x74\x20\x6f\x66\x20\x73\x70\x65\x63\x69\x61\x6c\x20\x63\x61\x73\x65\x73\x20\x74\x6f\x20\x61\x70\x70\x6c\x79\x20\x74\x6f\x20\x74\x68\x65\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x73\x0a\x20\x20\x20\x20\x6c\x6f\x63\x61\x6c\x20\x2d\x72\x20\x65\x78\x63\x65\x70\x74\x69\x6f\x6e\x5f\x72\x65\x67\x65\x78\x70\x73\x3d\x28\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x22\x73\x2f\x73\x61\x73\x6c\x5c\x2e\x73\x73\x6c\x2f\x73\x61\x73\x6c\x5f\x73\x73\x6c\x2f\x67\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x22\x73\x2f\x73\x61\x73\x6c\x5c\x2e\x70\x6c\x61\x69\x6e\x74\x65\x78\x74\x2f\x73\x61\x73\x6c\x5f\x70\x6c\x61\x69\x6e\x74\x65\x78\x74\x2f\x67\x22\x0a\x20\x20\x20\x20\x29\x0a\x20\x20\x20\x20\x23\x20\x4d\x61\x70\x20\x65\x6e\x76\x69\x72\x6f\x6e\x6d\x65\x6e\x74\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x73\x20\x74\x6f\x20\x63\x6f\x6e\x66\x69\x67\x20\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x0a\x20\x20\x20\x20\x66\x6f\x72\x20\x76\x61\x72\x20\x69\x6e\x20\x22\x24\x7b\x21\x4b\x41\x46\x4b\x41\x5f\x43\x46\x47\x5f\x40\x7d\x22\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6b\x65\x79\x3d\x22\x24\x28\x65\x63\x68\x6f\x20\x22\x24\x76\x61\x72\x22\x20\x7c\x20\x73\x65\x64\x20\x2d\x65\x20\x27\x73\x2f\x5e\x4b\x41\x46\x4b\x41\x5f\x43\x46\x47\x5f\x2f\x2f\x67\x27\x20\x2d\x65\x20\x27\x73\x2f\x5f\x2f\x5c\x2e\x2f\x67\x27\x20\x7c\x20\x74\x72\x20\x27\x5b\x3a\x75\x70\x70\x65\x72\x3a\x5d\x27\x20\x27\x5b\x3a\x6c\x6f\x77\x65\x72\x3a\x5d\x27\x29\x22\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x23\x20\x45\x78\x63\x65\x70\x74\x69\x6f\x6e\x20\x66\x6f\x72\x20\x74\x68\x65\x20\x63\x61\x6d\x65\x6c\x20\x63\x61\x73\x65\x20\x69\x6e\x20\x74\x68\x69\x73\x20\x65\x6e\x76\x69\x72\x6f\x6e\x6d\x65\x6e\x74\x20\x76\x61\x72\x69\x61\x62\x6c\x65\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x5b\x5b\x20\x22\x24\x76\x61\x72\x22\x20\x3d\x3d\x20\x22\x4b\x41\x46\x4b\x41\x5f\x43\x46\x47\x5f\x5a\x4f\x4f\x4b\x45\x45\x50\x45\x52\x5f\x43\x4c\x49\x45\x4e\x54\x43\x4e\x58\x4e\x53\x4f\x43\x4b\x45\x54\x22\x20\x5d\x5d\x20\x26\x26\x20\x6b\x65\x79\x3d\x22\x7a\x6f\x6f\x6b\x65\x65\x70\x65\x72\x2e\x63\x6c\x69\x65\x6e\x74\x43\x6e\x78\x6e\x53\x6f\x63\x6b\x65\x74\x22\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x23\x20\x41\x70\x70\x6c\x79\x20\x65\x78\x63\x65\x70\x74\x69\x6f\x6e\x20\x72\x65\x67\x65\x78\x70\x73\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x66\x6f\x72\x20\x72\x65\x67\x65\x78\x20\x69\x6e\x20\x22\x24\x7b\x65\x78\x63\x65\x70\x74\x69\x6f\x6e\x5f\x72\x65\x67\x65\x78\x70\x73\x5b\x40\x5d\x7d\x22\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x6b\x65\x79\x3d\x22\x24\x28\x65\x63\x68\x6f\x20\x22\x24\x6b\x65\x79\x22\x20\x7c\x20\x73\x65\x64\x20\x22\x24\x72\x65\x67\x65\x78\x22\x29\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x64\x6f\x6e\x65\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x76\x61\x6c\x75\x65\x3d\x22\x24\x7b\x21\x76\x61\x72\x7d\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x64\x64\x5f\x6f\x72\x5f\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x24\x7b\x6b\x65\x79\x7d\x22\x20\x22\x24\x7b\x76\x61\x6c\x75\x65\x7d\x22\x20\x22\x24\x7b\x66\x69\x6c\x65\x5f\x6e\x61\x6d\x65\x7d\x22\x0a\x20\x20\x20\x20\x64\x6f\x6e\x65\x0a\x7d\x0a\x0a\x6b\x61\x66\x6b\x61\x5f\x75\x70\x28\x29\x20\x7b\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x6b\x61\x66\x6b\x61\x5f\x75\x70\x3a\x20\x73\x74\x61\x72\x74\x22\x0a\x0a\x20\x20\x77\x68\x69\x6c\x65\x20\x5b\x5b\x20\x24\x23\x20\x2d\x67\x65\x20\x31\x20\x5d\x5d\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x20\x20\x63\x61\x73\x65\x20\x22\x24\x7b\x31\x7d\x22\x20\x69\x6e\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x70\x72\x6f\x63\x65\x73\x73\x2e\x72\x6f\x6c\x65\x73\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x72\x6f\x6c\x65\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x6e\x6f\x64\x65\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x6e\x6f\x64\x65\x2e\x69\x64\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x6e\x6f\x64\x65\x5f\x69\x64\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x69\x64\x20\x6f\x66\x20\x74\x68\x69\x73\x20\x6e\x6f\x64\x65\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x71\x75\x6f\x72\x75\x6d\x2e\x76\x6f\x74\x65\x72\x73\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x71\x75\x6f\x72\x75\x6d\x5f\x76\x6f\x74\x65\x72\x73\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x20\x71\x75\x6f\x72\x75\x6d\x20\x76\x6f\x74\x65\x72\x73\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x72\x65\x67\x69\x6f\x6e\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x72\x65\x67\x69\x6f\x6e\x73\x20\x6f\x66\x20\x73\x33\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x62\x75\x63\x6b\x65\x74\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x62\x75\x63\x6b\x65\x74\x20\x6e\x61\x6d\x65\x20\x6f\x66\x20\x73\x33\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x63\x6c\x75\x73\x74\x65\x72\x2e\x69\x64\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x63\x6c\x75\x73\x74\x65\x72\x5f\x69\x64\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x6b\x61\x66\x6b\x61\x20\x63\x6c\x75\x73\x74\x65\x72\x20\x69\x64\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x61\x63\x63\x65\x73\x73\x2e\x6b\x65\x79\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x61\x63\x63\x65\x73\x73\x5f\x6b\x65\x79\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x73\x33\x20\x61\x63\x63\x65\x73\x73\x20\x6b\x65\x79\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x73\x65\x63\x72\x65\x74\x2e\x6b\x65\x79\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x73\x65\x63\x72\x65\x74\x5f\x6b\x65\x79\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x73\x33\x20\x73\x65\x63\x72\x65\x74\x20\x6b\x65\x79\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x65\x6e\x64\x70\x6f\x69\x6e\x74\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x73\x33\x20\x65\x6e\x64\x70\x6f\x69\x6e\x74\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2d\x2d\x73\x33\x2e\x70\x61\x74\x68\x2e\x73\x74\x79\x6c\x65\x29\x20\x73\x65\x74\x5f\x6f\x6e\x63\x65\x20\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x20\x22\x24\x7b\x32\x7d\x22\x20\x22\x73\x33\x20\x70\x61\x74\x68\x20\x73\x74\x79\x6c\x65\x22\x3b\x20\x73\x68\x69\x66\x74\x20\x32\x3b\x3b\x0a\x20\x20\x20\x20\x20\x20\x65\x73\x61\x63\x0a\x20\x20\x64\x6f\x6e\x65\x0a\x0a\x20\x20\x70\x69\x64\x3d\x24\x28\x6a\x63\x6d\x64\x20\x7c\x20\x67\x72\x65\x70\x20\x2d\x65\x20\x6b\x61\x66\x6b\x61\x2e\x4b\x61\x66\x6b\x61\x20\x7c\x20\x61\x77\x6b\x20\x27\x7b\x70\x72\x69\x6e\x74\x20\x24\x31\x7d\x27\x29\x0a\x20\x20\x69\x66\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x70\x69\x64\x7d\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x65\x63\x68\x6f\x20\x22\x6b\x61\x66\x6b\x61\x5f\x75\x70\x3a\x20\x6b\x61\x66\x6b\x61\x20\x69\x73\x20\x61\x6c\x72\x65\x61\x64\x79\x20\x72\x75\x6e\x6e\x69\x6e\x67\x2c\x20\x70\x69\x64\x3d\x24\x7b\x70\x69\x64\x7d\x22\x0a\x20\x20\x20\x20\x20\x20\x65\x78\x69\x74\x20\x30\x0a\x20\x20\x66\x69\x0a\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x6e\x6f\x64\x65\x5f\x69\x64\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x6e\x6f\x64\x65\x5f\x69\x64\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x71\x75\x6f\x72\x75\x6d\x5f\x76\x6f\x74\x65\x72\x73\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x71\x75\x6f\x72\x75\x6d\x5f\x76\x6f\x74\x65\x72\x73\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x3d\x22\x24\x7b\x41\x57\x53\x5f\x44\x45\x46\x41\x55\x4c\x54\x5f\x52\x45\x47\x49\x4f\x4e\x7d\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x61\x63\x63\x65\x73\x73\x5f\x6b\x65\x79\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x73\x33\x5f\x61\x63\x63\x65\x73\x73\x5f\x6b\x65\x79\x3d\x22\x24\x7b\x4b\x41\x46\x4b\x41\x5f\x53\x33\x5f\x41\x43\x43\x45\x53\x53\x5f\x4b\x45\x59\x7d\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x73\x65\x63\x72\x65\x74\x5f\x6b\x65\x79\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x73\x33\x5f\x73\x65\x63\x72\x65\x74\x5f\x6b\x65\x79\x3d\x22\x24\x7b\x4b\x41\x46\x4b\x41\x5f\x53\x33\x5f\x53\x45\x43\x52\x45\x54\x5f\x4b\x45\x59\x7d\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x64\x69\x65\x20\x22\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x20\x69\x73\x20\x65\x6d\x70\x74\x79\x22\x0a\x20\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x63\x6c\x75\x73\x74\x65\x72\x5f\x69\x64\x7d\x22\x20\x5d\x5d\x20\x7c\x7c\x20\x63\x6c\x75\x73\x74\x65\x72\x5f\x69\x64\x3d\x22\x72\x5a\x64\x45\x30\x44\x6a\x5a\x53\x72\x71\x79\x39\x36\x50\x58\x72\x4d\x55\x5a\x56\x77\x22\x0a\x0a\x20\x20\x66\x6f\x72\x20\x72\x6f\x6c\x65\x20\x69\x6e\x20\x22\x62\x72\x6f\x6b\x65\x72\x22\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x22\x20\x22\x73\x65\x72\x76\x65\x72\x22\x3b\x20\x64\x6f\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6e\x6f\x64\x65\x2e\x69\x64\x22\x20\x22\x24\x7b\x6e\x6f\x64\x65\x5f\x69\x64\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x2e\x71\x75\x6f\x72\x75\x6d\x2e\x76\x6f\x74\x65\x72\x73\x22\x20\x22\x24\x7b\x71\x75\x6f\x72\x75\x6d\x5f\x76\x6f\x74\x65\x72\x73\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x73\x33\x2e\x64\x61\x74\x61\x2e\x62\x75\x63\x6b\x65\x74\x73\x22\x20\x22\x30\x40\x73\x33\x3a\x2f\x2f\x24\x7b\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x7d\x3f\x72\x65\x67\x69\x6f\x6e\x3d\x24\x7b\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x7d\x26\x65\x6e\x64\x70\x6f\x69\x6e\x74\x3d\x24\x7b\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x7d\x26\x61\x75\x74\x68\x54\x79\x70\x65\x3d\x73\x74\x61\x74\x69\x63\x26\x70\x61\x74\x68\x53\x74\x79\x6c\x65\x3d\x24\x7b\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x73\x33\x2e\x6f\x70\x73\x2e\x62\x75\x63\x6b\x65\x74\x73\x22\x20\x22\x30\x40\x73\x33\x3a\x2f\x2f\x24\x7b\x73\x33\x5f\x62\x75\x63\x6b\x65\x74\x7d\x3f\x72\x65\x67\x69\x6f\x6e\x3d\x24\x7b\x73\x33\x5f\x72\x65\x67\x69\x6f\x6e\x7d\x26\x65\x6e\x64\x70\x6f\x69\x6e\x74\x3d\x24\x7b\x73\x33\x5f\x65\x6e\x64\x70\x6f\x69\x6e\x74\x7d\x26\x61\x75\x74\x68\x54\x79\x70\x65\x3d\x73\x74\x61\x74\x69\x63\x26\x70\x61\x74\x68\x53\x74\x79\x6c\x65\x3d\x24\x7b\x73\x33\x5f\x70\x61\x74\x68\x5f\x73\x74\x79\x6c\x65\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6c\x6f\x67\x2e\x64\x69\x72\x73\x22\x20\x22\x24\x7b\x64\x61\x74\x61\x5f\x70\x61\x74\x68\x7d\x2f\x6b\x72\x61\x66\x74\x2d\x24\x7b\x72\x6f\x6c\x65\x7d\x2d\x6c\x6f\x67\x73\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x73\x33\x2e\x77\x61\x6c\x2e\x70\x61\x74\x68\x22\x20\x22\x30\x40\x66\x69\x6c\x65\x3a\x2f\x2f\x24\x7b\x64\x61\x74\x61\x5f\x70\x61\x74\x68\x7d\x2f\x77\x61\x6c\x3f\x63\x61\x70\x61\x63\x69\x74\x79\x3d\x32\x31\x34\x37\x34\x38\x33\x36\x34\x38\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x20\x20\x20\x20\x23\x20\x74\x75\x72\x6e\x20\x6f\x6e\x20\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x0a\x20\x20\x20\x20\x20\x20\x74\x75\x72\x6e\x5f\x6f\x6e\x5f\x61\x75\x74\x6f\x5f\x62\x61\x6c\x61\x6e\x63\x65\x72\x20\x22\x24\x7b\x72\x6f\x6c\x65\x7d\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x20\x20\x64\x6f\x6e\x65\x0a\x0a\x20\x20\x69\x66\x20\x5b\x5b\x20\x2d\x6e\x20\x22\x24\x7b\x4b\x41\x46\x4b\x41\x5f\x48\x45\x41\x50\x5f\x4f\x50\x54\x53\x7d\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x6b\x61\x66\x6b\x61\x5f\x68\x65\x61\x70\x5f\x6f\x70\x74\x73\x3d\x22\x24\x7b\x4b\x41\x46\x4b\x41\x5f\x48\x45\x41\x50\x5f\x4f\x50\x54\x53\x7d\x22\x0a\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x62\x72\x6f\x6b\x65\x72\x22\x20\x7c\x7c\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x73\x65\x72\x76\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x6b\x61\x66\x6b\x61\x5f\x68\x65\x61\x70\x5f\x6f\x70\x74\x73\x3d\x22\x2d\x58\x6d\x73\x31\x67\x20\x2d\x58\x6d\x78\x31\x67\x20\x2d\x58\x58\x3a\x4d\x65\x74\x61\x73\x70\x61\x63\x65\x53\x69\x7a\x65\x3d\x39\x36\x6d\x20\x2d\x58\x58\x3a\x4d\x61\x78\x44\x69\x72\x65\x63\x74\x4d\x65\x6d\x6f\x72\x79\x53\x69\x7a\x65\x3d\x31\x47\x22\x0a\x20\x20\x65\x6c\x69\x66\x20\x5b\x5b\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x3d\x3d\x20\x22\x63\x6f\x6e\x74\x72\x6f\x6c\x6c\x65\x72\x22\x20\x5d\x5d\x3b\x20\x74\x68\x65\x6e\x0a\x20\x20\x20\x20\x20\x20\x6b\x61\x66\x6b\x61\x5f\x68\x65\x61\x70\x5f\x6f\x70\x74\x73\x3d\x22\x2d\x58\x6d\x73\x31\x67\x20\x2d\x58\x6d\x78\x31\x67\x20\x2d\x58\x58\x3a\x4d\x65\x74\x61\x73\x70\x61\x63\x65\x53\x69\x7a\x65\x3d\x39\x36\x6d\x22\x0a\x20\x20\x65\x6c\x73\x65\x0a\x20\x20\x20\x20\x20\x20\x64\x69\x65\x20\x22\x6b\x61\x66\x6b\x61\x5f\x73\x74\x61\x72\x74\x5f\x75\x70\x3a\x20\x75\x6e\x6b\x6e\x6f\x77\x6e\x20\x70\x72\x6f\x63\x65\x73\x73\x20\x72\x6f\x6c\x65\x20\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x0a\x20\x20\x66\x69\x0a\x20\x20\x65\x78\x70\x6f\x72\x74\x20\x4b\x41\x46\x4b\x41\x5f\x48\x45\x41\x50\x5f\x4f\x50\x54\x53\x3d\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x68\x65\x61\x70\x5f\x6f\x70\x74\x73\x7d\x22\x0a\x0a\x20\x20\x23\x20\x61\x64\x64\x20\x74\x68\x69\x73\x20\x6e\x6f\x64\x65\x27\x73\x20\x69\x6e\x66\x6f\x20\x74\x6f\x20\x72\x75\x6e\x2e\x69\x6e\x66\x6f\x0a\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6e\x6f\x64\x65\x2e\x69\x64\x22\x20\x22\x24\x7b\x6e\x6f\x64\x65\x5f\x69\x64\x7d\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x72\x6f\x6c\x65\x22\x20\x22\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6b\x61\x66\x6b\x61\x2e\x62\x61\x73\x65\x2e\x70\x61\x74\x68\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x0a\x20\x20\x73\x65\x74\x75\x70\x5f\x76\x61\x6c\x75\x65\x20\x22\x6b\x61\x66\x6b\x61\x2e\x64\x61\x74\x61\x2e\x70\x61\x74\x68\x22\x20\x22\x24\x7b\x64\x61\x74\x61\x5f\x70\x61\x74\x68\x7d\x22\x20\x22\x24\x7b\x72\x75\x6e\x5f\x69\x6e\x66\x6f\x5f\x66\x69\x6c\x65\x7d\x22\x0a\x0a\x20\x20\x23\x20\x63\x68\x61\x6e\x67\x65\x20\x69\x70\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x68\x65\x72\x65\x0a\x20\x20\x6b\x61\x66\x6b\x61\x5f\x6d\x6f\x6e\x69\x74\x6f\x72\x5f\x69\x70\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x6b\x61\x66\x6b\x61\x5f\x75\x70\x3a\x20\x69\x70\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x63\x68\x61\x6e\x67\x65\x64\x22\x0a\x0a\x20\x20\x23\x20\x6f\x76\x65\x72\x72\x69\x64\x65\x20\x73\x65\x74\x74\x69\x6e\x67\x73\x20\x66\x72\x6f\x6d\x20\x65\x6e\x76\x0a\x20\x20\x63\x6f\x6e\x66\x69\x67\x75\x72\x65\x5f\x66\x72\x6f\x6d\x5f\x65\x6e\x76\x69\x72\x6f\x6e\x6d\x65\x6e\x74\x5f\x76\x61\x72\x69\x61\x62\x6c\x65\x73\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x0a\x20\x20\x23\x20\x44\x69\x73\x61\x62\x6c\x65\x20\x74\x68\x65\x20\x64\x65\x66\x61\x75\x6c\x74\x20\x63\x6f\x6e\x73\x6f\x6c\x65\x20\x6c\x6f\x67\x67\x65\x72\x20\x69\x6e\x20\x66\x61\x76\x6f\x75\x72\x20\x6f\x66\x20\x4b\x61\x66\x6b\x61\x41\x70\x70\x65\x6e\x64\x65\x72\x20\x28\x77\x68\x69\x63\x68\x20\x70\x72\x6f\x76\x69\x64\x65\x73\x20\x74\x68\x65\x20\x65\x78\x61\x63\x74\x20\x6f\x75\x74\x70\x75\x74\x29\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x6c\x6f\x67\x34\x6a\x2e\x61\x70\x70\x65\x6e\x64\x65\x72\x2e\x73\x74\x64\x6f\x75\x74\x2e\x54\x68\x72\x65\x73\x68\x6f\x6c\x64\x3d\x4f\x46\x46\x22\x20\x3e\x3e\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6c\x6f\x67\x34\x6a\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x0a\x20\x20\x23\x20\x66\x6f\x72\x6d\x61\x74\x20\x74\x68\x65\x20\x64\x61\x74\x61\x20\x70\x61\x74\x68\x0a\x20\x20\x6d\x75\x73\x74\x5f\x64\x6f\x20\x2d\x76\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x62\x69\x6e\x2f\x6b\x61\x66\x6b\x61\x2d\x73\x74\x6f\x72\x61\x67\x65\x2e\x73\x68\x20\x66\x6f\x72\x6d\x61\x74\x20\x2d\x67\x20\x2d\x74\x20\x24\x7b\x63\x6c\x75\x73\x74\x65\x72\x5f\x69\x64\x7d\x20\x2d\x63\x20\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x0a\x20\x20\x65\x78\x65\x63\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x62\x69\x6e\x2f\x6b\x61\x66\x6b\x61\x2d\x73\x65\x72\x76\x65\x72\x2d\x73\x74\x61\x72\x74\x2e\x73\x68\x22\x20\x22\x24\x7b\x6b\x61\x66\x6b\x61\x5f\x64\x69\x72\x7d\x2f\x63\x6f\x6e\x66\x69\x67\x2f\x6b\x72\x61\x66\x74\x2f\x24\x7b\x70\x72\x6f\x63\x65\x73\x73\x5f\x72\x6f\x6c\x65\x7d\x2e\x70\x72\x6f\x70\x65\x72\x74\x69\x65\x73\x22\x0a\x7d\x0a\x0a\x23\x20\x50\x61\x72\x73\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x2d\x6c\x69\x6e\x65\x20\x61\x72\x67\x75\x6d\x65\x6e\x74\x73\x0a\x5b\x5b\x20\x24\x23\x20\x2d\x6c\x74\x20\x31\x20\x5d\x5d\x20\x26\x26\x20\x75\x73\x61\x67\x65\x20\x30\x0a\x23\x20\x44\x69\x73\x70\x6c\x61\x79\x20\x74\x68\x65\x20\x68\x65\x6c\x70\x20\x74\x65\x78\x74\x20\x69\x66\x20\x2d\x68\x20\x6f\x72\x20\x2d\x2d\x68\x65\x6c\x70\x20\x61\x70\x70\x65\x61\x72\x73\x20\x69\x6e\x20\x74\x68\x65\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x6c\x69\x6e\x65\x0a\x66\x6f\x72\x20\x61\x72\x67\x20\x69\x6e\x20\x22\x24\x7b\x40\x7d\x22\x3b\x20\x64\x6f\x0a\x20\x20\x63\x61\x73\x65\x20\x22\x24\x7b\x61\x72\x67\x7d\x22\x20\x69\x6e\x0a\x20\x20\x2d\x68\x20\x7c\x20\x2d\x2d\x68\x65\x6c\x70\x29\x20\x75\x73\x61\x67\x65\x20\x30\x20\x3b\x3b\x0a\x20\x20\x2d\x2d\x29\x20\x62\x72\x65\x61\x6b\x20\x3b\x3b\x0a\x20\x20\x2a\x29\x20\x3b\x3b\x0a\x20\x20\x65\x73\x61\x63\x0a\x64\x6f\x6e\x65\x0a\x61\x63\x74\x69\x6f\x6e\x3d\x22\x24\x7b\x31\x7d\x22\x0a\x73\x68\x69\x66\x74\x0a\x63\x61\x73\x65\x20\x22\x24\x7b\x61\x63\x74\x69\x6f\x6e\x7d\x22\x20\x69\x6e\x0a\x68\x65\x6c\x70\x29\x20\x75\x73\x61\x67\x65\x20\x30\x20\x3b\x3b\x0a\x0a\x75\x70\x29\x0a\x20\x20\x6b\x61\x66\x6b\x61\x5f\x22\x24\x7b\x61\x63\x74\x69\x6f\x6e\x7d\x22\x20\x22\x24\x7b\x40\x7d\x22\x0a\x20\x20\x65\x78\x69\x74\x20\x30\x0a\x20\x20\x3b\x3b\x0a\x0a\x2a\x29\x0a\x20\x20\x65\x63\x68\x6f\x20\x22\x55\x6e\x6b\x6e\x6f\x77\x6e\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x20\x27\x24\x7b\x61\x63\x74\x69\x6f\x6e\x7d\x27\x2e\x20\x20\x54\x79\x70\x65\x20\x27\x24\x7b\x73\x63\x72\x69\x70\x74\x5f\x70\x61\x74\x68\x7d\x20\x2d\x2d\x68\x65\x6c\x70\x27\x20\x66\x6f\x72\x20\x75\x73\x61\x67\x65\x20\x69\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\x2e\x22\x0a\x20\x20\x65\x78\x69\x74\x20\x31\x0a\x20\x20\x3b\x3b\x0a\x65\x73\x61\x63\x0a" func defaultsUpShBytes() ([]byte, error) { return bindataRead( @@ -82,7 +82,7 @@ func defaultsUpSh() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "defaults/up.sh", size: 12068, mode: os.FileMode(420), modTime: time.Unix(1728819272, 0)} + info := bindataFileInfo{name: "defaults/up.sh", size: 12447, mode: os.FileMode(420), modTime: time.Unix(1728831987, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/deploy/charts/automq-operator/crds/infra.cuisongliu.github.com_automqs.yaml b/deploy/charts/automq-operator/crds/infra.cuisongliu.github.com_automqs.yaml index 3c4c8d5..bb4d518 100644 --- a/deploy/charts/automq-operator/crds/infra.cuisongliu.github.com_automqs.yaml +++ b/deploy/charts/automq-operator/crds/infra.cuisongliu.github.com_automqs.yaml @@ -597,6 +597,10 @@ spec: required: - enable type: object + nodePort: + description: NodePort is the node port of the AutoMQ + format: int32 + type: integer s3: description: S3 is the S3 configuration for the AutoMQ properties: diff --git a/deploy/charts/automq-operator/templates/deployment.yaml b/deploy/charts/automq-operator/templates/deployment.yaml index 05b6cbf..aab3ecd 100644 --- a/deploy/charts/automq-operator/templates/deployment.yaml +++ b/deploy/charts/automq-operator/templates/deployment.yaml @@ -53,6 +53,8 @@ spec: apiVersion: v1 - name: ENABLE_WEBHOOKS value: "{{.Values.webhook.enabled}}" + - name: OPERATOR_APIS_SVC_NAME + value: "{{ include "automq-operator.fullname" . }}-apis" ports: - containerPort: 9443 name: webhook-server @@ -60,6 +62,9 @@ spec: - name: http containerPort: 8081 protocol: TCP + - name: apis + containerPort: 9090 + protocol: TCP livenessProbe: httpGet: path: /healthz diff --git a/deploy/charts/automq-operator/templates/service.yaml b/deploy/charts/automq-operator/templates/service.yaml index 0f3106f..544c1ad 100644 --- a/deploy/charts/automq-operator/templates/service.yaml +++ b/deploy/charts/automq-operator/templates/service.yaml @@ -16,4 +16,18 @@ spec: {{- include "automq-operator.selectorLabels" . | nindent 4 }} {{- end }} --- - +apiVersion: v1 +kind: Service +metadata: + name: {{ include "automq-operator.fullname" . }}-apis + labels: + {{- include "automq-operator.labels" . | nindent 4 }} + app: k8s-api +spec: + ports: + - name: apis + port: 9090 + protocol: TCP + targetPort: apis + selector: + {{- include "automq-operator.selectorLabels" . | nindent 4 }} diff --git a/go.mod b/go.mod index 76366f9..5047524 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.17.38 github.com/aws/aws-sdk-go-v2/service/s3 v1.64.1 github.com/cuisongliu/logger v0.0.0-20230412024334-6d0345c427ba + github.com/gin-gonic/gin v1.10.0 github.com/go-bindata/go-bindata v3.1.2+incompatible github.com/labring/operator-sdk v1.0.5 github.com/onsi/ginkgo/v2 v2.14.0 @@ -36,17 +37,27 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.31.4 // indirect github.com/aws/smithy-go v1.21.0 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.8.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect @@ -58,30 +69,38 @@ require ( github.com/imdario/mergo v0.3.12 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.21.0 // indirect + golang.org/x/net v0.25.0 // indirect golang.org/x/oauth2 v0.12.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/term v0.17.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/term v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.16.1 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 2811e32..0ef47f4 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,10 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -98,6 +102,10 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -143,7 +151,13 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE= github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -177,10 +191,20 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -308,6 +332,10 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -323,6 +351,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/labring/operator-sdk v1.0.5 h1:0+yUyoAzQPSi1t+LHMVMuwGQpZ6aHiIlUu8e89Qy30s= github.com/labring/operator-sdk v1.0.5/go.mod h1:4KBQDNlocY+VUY2rgdW9Jz1aCkZMLN3IKdGUuDiXx18= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -332,6 +362,8 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -383,6 +415,8 @@ github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -458,6 +492,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -467,11 +502,16 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -498,6 +538,9 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -508,6 +551,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -572,8 +617,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -633,13 +678,15 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -647,8 +694,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -763,8 +810,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -835,7 +882,9 @@ k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20210527160623-6fdb442a123b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ= k8s.io/utils v0.0.0-20240102154912-e7106e64919e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= diff --git a/internal/controller/automq_controller.go b/internal/controller/automq_controller.go index b3d64b3..608cd7d 100644 --- a/internal/controller/automq_controller.go +++ b/internal/controller/automq_controller.go @@ -62,7 +62,13 @@ func (r *AutoMQReconciler) doFinalizerOperationsForSetting(ctx context.Context, } func (r *AutoMQReconciler) cleanup(ctx context.Context, automq *infrav1beta1.AutoMQ) error { - err := r.cleanController(ctx, automq) + err := r.cleanBroker(ctx, automq) + if err != nil { + if !apierrors.IsNotFound(err) { + return err + } + } + err = r.cleanController(ctx, automq) if err != nil { if !apierrors.IsNotFound(err) { return err @@ -161,6 +167,9 @@ func (r *AutoMQReconciler) reconcile(ctx context.Context, obj client.Object) (ct r.scriptConfigmap, r.syncControllersScale, r.syncControllers, + r.syncBrokerScale, + r.syncBrokers, + r.syncKafkaBootstrapService, } for _, fn := range pipelines { diff --git a/internal/controller/automq_controller_b.go b/internal/controller/automq_controller_b.go new file mode 100644 index 0000000..3ca3bac --- /dev/null +++ b/internal/controller/automq_controller_b.go @@ -0,0 +1,484 @@ +/* +Copyright 2024 cuisongliu@qq.com. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package controller + +import ( + "context" + "fmt" + "os" + "strconv" + "strings" + + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/aws/aws-sdk-go-v2/aws" + infrav1beta1 "github.com/cuisongliu/automq-operator/api/v1beta1" + "github.com/cuisongliu/automq-operator/defaults" + appsv1 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/util/retry" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +const ( + brokerRole = "broker" +) + +func (r *AutoMQReconciler) cleanBroker(ctx context.Context, obj *infrav1beta1.AutoMQ) error { + for i := 0; i < int(obj.Status.BrokerReplicas); i++ { + svcc := &v1.Service{} + svcc.Namespace = obj.Namespace + index := int32(i) + svcc.Name = getAutoMQName(brokerRole, &index) + _ = r.Client.Delete(ctx, svcc) + + deploy := &appsv1.StatefulSet{} + deploy.Namespace = obj.Namespace + deploy.Name = getAutoMQName(brokerRole, &index) + _ = r.Client.Delete(ctx, deploy) + + pvc := &v1.PersistentVolumeClaim{} + pvc.Namespace = obj.Namespace + pvc.Name = getAutoMQName(brokerRole, &index) + _ = r.Client.Delete(ctx, pvc) + } + return nil +} + +func (r *AutoMQReconciler) syncBrokerScale(ctx context.Context, obj *infrav1beta1.AutoMQ) context.Context { + conditionType := "SyncBrokerScale" + currentReplicas := obj.Status.BrokerReplicas + if currentReplicas > obj.Spec.Broker.Replicas { + for i := obj.Spec.Broker.Replicas; i < currentReplicas; i++ { + deploy := &appsv1.StatefulSet{} + deploy.Namespace = obj.Namespace + deploy.Name = getAutoMQName(brokerRole, &i) + _ = r.Client.Delete(ctx, deploy) + svc := &v1.Service{} + svc.Namespace = obj.Namespace + svc.Name = getAutoMQName(brokerRole, &i) + _ = r.Client.Delete(ctx, svc) + pvc := &v1.PersistentVolumeClaim{} + pvc.Namespace = obj.Namespace + pvc.Name = getAutoMQName(brokerRole, &i) + _ = r.Client.Delete(ctx, pvc) + } + } + meta.SetStatusCondition(&obj.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionTrue, + ObservedGeneration: obj.Generation, + Reason: "BrokerScaleReconciling", + Message: fmt.Sprintf("Broker scale for the custom resource (%s) has been reconciled", obj.Name), + }) + return ctx +} + +func (r *AutoMQReconciler) syncBrokers(ctx context.Context, obj *infrav1beta1.AutoMQ) context.Context { + conditionType := "SyncBrokerReady" + + // 1. sync pvc + // 2. sync deploy + // 3. sync svc + // 3. sync monitor + + for i := 0; i < int(obj.Spec.Broker.Replicas); i++ { + if err := r.syncBrokerPVC(ctx, obj, int32(i)); err != nil { + meta.SetStatusCondition(&obj.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + ObservedGeneration: obj.Generation, + Reason: "BrokerPVCReconciling", + Message: fmt.Sprintf("Failed to create pvc for the custom resource (%s): (%s)", obj.Name, err), + }) + return ctx + } + if err := r.syncBrokerService(ctx, obj, int32(i)); err != nil { + meta.SetStatusCondition(&obj.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + ObservedGeneration: obj.Generation, + Reason: "BrokerServiceReconciling", + Message: fmt.Sprintf("Failed to create service for the custom resource (%s): (%s)", obj.Name, err), + }) + return ctx + } + if err := r.syncBrokerDeploy(ctx, obj, int32(i)); err != nil { + meta.SetStatusCondition(&obj.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + ObservedGeneration: obj.Generation, + Reason: "BrokerSTSReconciling", + Message: fmt.Sprintf("Failed to create deploy for the custom resource (%s): (%s)", obj.Name, err), + }) + return ctx + } + } + meta.SetStatusCondition(&obj.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionTrue, + ObservedGeneration: obj.Generation, + Reason: "BrokerReconciling", + Message: fmt.Sprintf("Broker resource for the custom resource (%s) has been created or update", obj.Name), + }) + return ctx +} + +func (r *AutoMQReconciler) syncBrokerPVC(ctx context.Context, obj *infrav1beta1.AutoMQ, index int32) error { + storage, _ := resource.ParseQuantity("100Gi") + pvc := &v1.PersistentVolumeClaim{} + pvc.Namespace = obj.Namespace + pvc.Name = getAutoMQName(brokerRole, &index) + labelMap := getAutoMQLabelMap(obj.GetName(), brokerRole) + labelMap[autoMQIndexKey] = fmt.Sprintf("%d", index) + if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + _, err := controllerutil.CreateOrUpdate(ctx, r.Client, pvc, func() error { + pvc.Labels = labelMap + pvc.Spec.AccessModes = []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce} + pvc.Spec.Resources = v1.VolumeResourceRequirements{ + Requests: v1.ResourceList{ + v1.ResourceStorage: storage, + }, + } + if obj.Spec.Broker.StorageClass != "" { + pvc.Spec.StorageClassName = &obj.Spec.Broker.StorageClass + } + return nil + }) + return err + }); err != nil { + return err + } + return nil +} + +func (r *AutoMQReconciler) syncBrokerDeploy(ctx context.Context, obj *infrav1beta1.AutoMQ, index int32) error { + deploy := &appsv1.Deployment{} + deploy.Namespace = obj.Namespace + deploy.Name = getAutoMQName(brokerRole, &index) + labelMap := getAutoMQLabelMap(obj.GetName(), brokerRole) + labelMap[autoMQIndexKey] = fmt.Sprintf("%d", index) + deploy.Spec.Selector = &metav1.LabelSelector{ + MatchLabels: labelMap, + } + svc := &v1.Service{} + svc.Namespace = obj.Namespace + svc.Name = getAutoMQName(brokerRole, &index) + + if err := r.Client.Get(ctx, client.ObjectKeyFromObject(svc), svc); err != nil { + return err + } + + sysctl := sysctlContainer() + envs := []v1.EnvVar{ + { + Name: "NAMESPACE_NAME", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.namespace", + }, + }, + }, + { + Name: "POD_NAME", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.name", + }, + }, + }, + { + Name: "NODE_NAME", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "spec.nodeName", + }, + }, + }, + { + Name: "POD_IP", + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "status.podIP", + }, + }, + }, + { + Name: "KAFKA_S3_ACCESS_KEY", + Value: obj.Spec.S3.AccessKeyID, + }, + { + Name: "KAFKA_S3_SECRET_KEY", + Value: obj.Spec.S3.SecretAccessKey, + }, + { + Name: "KAFKA_HEAP_OPTS", + Value: strings.Join(obj.Spec.Broker.JVMOptions, " "), + }, + { + Name: "KAFKA_CFG_AUTOBALANCER_REPORTER_NETWORK_IN_CAPACITY", + Value: "5120", + }, + { + Name: "KAFKA_CFG_AUTOBALANCER_REPORTER_NETWORK_OUT_CAPACITY", + Value: "5120", + }, + { + Name: "KAFKA_CFG_AUTOBALANCER_REPORTER_METRICS_REPORTING_INTERVAL_MS", + Value: "5000", + }, + { + Name: "NODEPORT_DEFAULT_PORT", + Value: strconv.Itoa(int(svc.Spec.Ports[0].NodePort)), + }, + { + Name: "OPERATOR_APIS_ADDR", + Value: fmt.Sprintf("http://%s.%s.svc:%d", os.Getenv("OPERATOR_APIS_SVC_NAME"), os.Getenv("NAMESPACE_NAME"), 9090), + }, + } + cmds := []string{ + "/opt/kafka/scripts/mq-start.sh", + "up", + "--process.roles", + "broker", + "--node.id", + fmt.Sprintf("%d", index), + "--cluster.id", + obj.Spec.ClusterID, + "--controller.quorum.voters", + strings.Join(r.controllerVoters(obj), ","), + "--s3.bucket", + obj.Spec.S3.Bucket, + "--s3.endpoint", + obj.Spec.S3.Endpoint, + "--s3.region", + obj.Spec.S3.Region, + "--s3.path.style", + fmt.Sprintf("%t", obj.Spec.S3.EnablePathStyle), + } + if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + _, err := controllerutil.CreateOrUpdate(ctx, r.Client, deploy, func() error { + deploy.Labels = getAutoMQLabelMap(obj.GetName(), brokerRole) + deploy.Spec.Strategy = appsv1.DeploymentStrategy{ + Type: appsv1.RollingUpdateDeploymentStrategyType, + } + deploy.Spec.Template.Labels = labelMap + deploy.Spec.Template.Spec.HostNetwork = false + deploy.Spec.Template.Spec.TerminationGracePeriodSeconds = aws.Int64(60 * 2) + deploy.Spec.Template.Spec.InitContainers = []v1.Container{ + sysctl, + } + deploy.Spec.Template.Spec.Affinity = obj.Spec.Broker.Affinity.ToK8sAffinity() + deploy.Spec.Template.Spec.Volumes = []v1.Volume{ + { + Name: "script", + VolumeSource: v1.VolumeSource{ + ConfigMap: &v1.ConfigMapVolumeSource{ + LocalObjectReference: v1.LocalObjectReference{ + Name: obj.Name, + }, + DefaultMode: aws.Int32(0755), + }, + }, + }, + { + Name: deploy.Name, + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: deploy.Name, + }, + }, + }, + } + deploy.Spec.Template.Spec.Containers = []v1.Container{ + { + Name: brokerRole, + Image: defaults.DefaultImageName, + Env: envs, + VolumeMounts: []v1.VolumeMount{ + { + Name: deploy.Name, + MountPath: "/data/kafka", + }, + { + Name: "script", + MountPath: "/opt/kafka/scripts/mq-start.sh", + SubPath: "up.sh", + ReadOnly: false, + }, + }, + Lifecycle: &v1.Lifecycle{ + PreStop: &v1.LifecycleHandler{ + Exec: &v1.ExecAction{ + Command: []string{ + "bash", + "-c", + "/opt/kafka/kafka/bin/kafka-server-stop.sh", + }, + }, + }, + }, + Command: []string{ + "/bin/bash", + "-c", + strings.Join(cmds, " \\\n"), + }, + LivenessProbe: &v1.Probe{ + ProbeHandler: v1.ProbeHandler{ + TCPSocket: &v1.TCPSocketAction{ + Port: intstr.FromString(brokerRole), + }, + }, + InitialDelaySeconds: 20, + TimeoutSeconds: 10, + PeriodSeconds: 30, + SuccessThreshold: 1, + FailureThreshold: 4, + TerminationGracePeriodSeconds: nil, + }, + Ports: []v1.ContainerPort{ + { + Name: brokerRole, + ContainerPort: 9092, + Protocol: v1.ProtocolTCP, + }, + }, + ImagePullPolicy: v1.PullIfNotPresent, + }, + } + hash, ok := ctx.Value(ctxKey("hash-configmap")).(string) + if !ok { + hash = "" + } + deploy.Spec.Template.Annotations = map[string]string{ + "configmap/script-hash": hash, + } + + if obj.Spec.Metrics.Enable { + deploy.Spec.Template.Spec.Containers[0].Env = append(deploy.Spec.Template.Spec.Containers[0].Env, v1.EnvVar{ + Name: "KAFKA_CFG_S3_TELEMETRY_METRICS_EXPORTER_URI", + Value: "prometheus://?host=0.0.0.0&port=9090", + }) + deploy.Spec.Template.Annotations["prometheus.io/scrape"] = "true" + deploy.Spec.Template.Annotations["prometheus.io/port"] = "9090" + deploy.Spec.Template.Annotations["prometheus.io/path"] = "/metrics" + } + if r.MountTZ { + deploy.Spec.Template.Spec.Volumes = append(deploy.Spec.Template.Spec.Volumes, v1.Volume{ + Name: "k8tz", + VolumeSource: v1.VolumeSource{ + HostPath: &v1.HostPathVolumeSource{ + Path: "/etc/localtime", + }, + }, + }) + deploy.Spec.Template.Spec.Containers[0].VolumeMounts = append(deploy.Spec.Template.Spec.Containers[0].VolumeMounts, v1.VolumeMount{ + Name: "k8tz", + MountPath: "/etc/localtime", + }) + } + if obj.Spec.Broker.Resource.Requests != nil { + deploy.Spec.Template.Spec.Containers[0].Resources.Requests = obj.Spec.Broker.Resource.Requests + } + if obj.Spec.Broker.Resource.Limits != nil { + deploy.Spec.Template.Spec.Containers[0].Resources.Limits = obj.Spec.Broker.Resource.Limits + } + if obj.Spec.Broker.Envs != nil && len(obj.Spec.Broker.Envs) > 0 { + deploy.Spec.Template.Spec.Containers[0].Env = append(deploy.Spec.Template.Spec.Containers[0].Env, obj.Spec.Broker.Envs...) + } + return nil + }) + return err + }); err != nil { + return err + } + return nil +} +func (r *AutoMQReconciler) syncBrokerService(ctx context.Context, obj *infrav1beta1.AutoMQ, index int32) error { + svc := &v1.Service{} + svc.Namespace = obj.Namespace + svc.Name = getAutoMQName(brokerRole, &index) + labelMap := getAutoMQLabelMap(obj.GetName(), brokerRole) + labelMap[autoMQIndexKey] = fmt.Sprintf("%d", index) + svc.Spec.Selector = labelMap + if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + _, err := controllerutil.CreateOrUpdate(ctx, r.Client, svc, func() error { + svc.Labels = labelMap + svc.Spec.Ports = []v1.ServicePort{ + { + Name: brokerRole, + Port: 9092, + TargetPort: intstr.FromString(brokerRole), + Protocol: v1.ProtocolTCP, + }, + } + svc.Spec.Type = v1.ServiceTypeNodePort + return nil + }) + return err + }); err != nil { + return err + } + return nil +} + +func (r *AutoMQReconciler) syncKafkaBootstrapService(ctx context.Context, obj *infrav1beta1.AutoMQ) context.Context { + log := log.FromContext(ctx) + conditionType := "SyncBootstrapServiceReady" + + svc := &v1.Service{} + svc.Namespace = obj.Namespace + svc.Name = getAutoMQName(brokerRole+"-bootstrap", nil) + labelMap := getAutoMQLabelMap(obj.GetName(), brokerRole) + svc.Spec.Selector = labelMap + var change controllerutil.OperationResult + var e error + if err := retry.RetryOnConflict(retry.DefaultRetry, func() error { + if change, e = controllerutil.CreateOrUpdate(ctx, r.Client, svc, func() error { + svc.Labels = labelMap + svc.Spec.Ports = []v1.ServicePort{ + { + Name: brokerRole, + Port: 9092, + TargetPort: intstr.FromString(brokerRole), + Protocol: v1.ProtocolTCP, + NodePort: obj.Spec.NodePort, + }, + } + svc.Spec.Type = v1.ServiceTypeNodePort + return nil + }); e != nil { + return e + } + log.V(1).Info("create or update bootstrap service by AutoMQ", "OperationResult", change) + return nil + }); err != nil { + meta.SetStatusCondition(&obj.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + ObservedGeneration: obj.Generation, + Reason: "BootstrapServiceReconciling", + Message: fmt.Sprintf("Failed to create bootstrap service for the custom resource (%s): (%s)", obj.Name, err), + }) + } + return nil +} diff --git a/internal/controller/automq_controller_c.go b/internal/controller/automq_controller_c.go index 557ceb6..7d8a3f5 100644 --- a/internal/controller/automq_controller_c.go +++ b/internal/controller/automq_controller_c.go @@ -46,10 +46,10 @@ func (r *AutoMQReconciler) cleanController(ctx context.Context, obj *infrav1beta svcc.Name = getAutoMQName(controllerRole, &index) _ = r.Client.Delete(ctx, svcc) - sts := &appsv1.StatefulSet{} - sts.Namespace = obj.Namespace - sts.Name = getAutoMQName(controllerRole, &index) - _ = r.Client.Delete(ctx, sts) + deploy := &appsv1.Deployment{} + deploy.Namespace = obj.Namespace + deploy.Name = getAutoMQName(controllerRole, &index) + _ = r.Client.Delete(ctx, deploy) pvc := &v1.PersistentVolumeClaim{} pvc.Namespace = obj.Namespace @@ -64,10 +64,10 @@ func (r *AutoMQReconciler) syncControllersScale(ctx context.Context, obj *infrav currentReplicas := obj.Status.ControllerReplicas if currentReplicas > obj.Spec.Controller.Replicas { for i := obj.Spec.Controller.Replicas; i < currentReplicas; i++ { - sts := &appsv1.StatefulSet{} - sts.Namespace = obj.Namespace - sts.Name = getAutoMQName(controllerRole, &i) - _ = r.Client.Delete(ctx, sts) + deploy := &appsv1.Deployment{} + deploy.Namespace = obj.Namespace + deploy.Name = getAutoMQName(controllerRole, &i) + _ = r.Client.Delete(ctx, deploy) svc := &v1.Service{} svc.Namespace = obj.Namespace svc.Name = getAutoMQName(controllerRole, &i) @@ -92,7 +92,7 @@ func (r *AutoMQReconciler) syncControllers(ctx context.Context, obj *infrav1beta conditionType := "SyncControllerReady" // 1. sync pvc - // 2. sync sts + // 2. sync deploy // 3. sync svc // 3. sync monitor @@ -113,7 +113,7 @@ func (r *AutoMQReconciler) syncControllers(ctx context.Context, obj *infrav1beta Status: metav1.ConditionFalse, ObservedGeneration: obj.Generation, Reason: "ControllerSTSReconciling", - Message: fmt.Sprintf("Failed to create sts for the custom resource (%s): (%s)", obj.Name, err), + Message: fmt.Sprintf("Failed to create deploy for the custom resource (%s): (%s)", obj.Name, err), }) return ctx } @@ -170,7 +170,7 @@ func (r *AutoMQReconciler) controllerVoters(obj *infrav1beta1.AutoMQ) []string { var voters []string for i := 0; i < int(obj.Spec.Controller.Replicas); i++ { index := int32(i) - voters = append(voters, fmt.Sprintf("%d@%s.%s.svc.cluster.local:%d", i, getAutoMQName(controllerRole, &index), obj.Namespace, 9093)) + voters = append(voters, fmt.Sprintf("%d@%s.%s.svc:%d", i, getAutoMQName(controllerRole, &index), obj.Namespace, 9093)) } return voters }