mirror of
				https://github.com/ggml-org/llama.cpp.git
				synced 2025-11-04 09:32:00 +00:00 
			
		
		
		
	Merge branch 'master' into HEAD
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							@@ -111,6 +111,7 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      - name: Dependencies
 | 
			
		||||
        id: depends
 | 
			
		||||
        continue-on-error: true
 | 
			
		||||
        run: |
 | 
			
		||||
          brew update
 | 
			
		||||
 | 
			
		||||
@@ -129,6 +130,7 @@ jobs:
 | 
			
		||||
 | 
			
		||||
      - name: Dependencies
 | 
			
		||||
        id: depends
 | 
			
		||||
        continue-on-error: true
 | 
			
		||||
        run: |
 | 
			
		||||
          brew update
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -79,7 +79,7 @@ option(LLAMA_QKK_64                          "llama: use super-block size of 64
 | 
			
		||||
 | 
			
		||||
option(LLAMA_BUILD_TESTS                "llama: build tests"    ${LLAMA_STANDALONE})
 | 
			
		||||
option(LLAMA_BUILD_EXAMPLES             "llama: build examples" ${LLAMA_STANDALONE})
 | 
			
		||||
option(LLAMA_BUILD_SERVER               "llama: build server example"                           OFF)
 | 
			
		||||
option(LLAMA_BUILD_SERVER               "llama: build server example"                           ON)
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Build info header
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,11 +1,5 @@
 | 
			
		||||
# Define the default target now so that it is always the first target
 | 
			
		||||
BUILD_TARGETS = main quantize quantize-stats perplexity embedding vdot train-text-from-scratch simple libembdinput.so embd-input-test
 | 
			
		||||
 | 
			
		||||
ifdef LLAMA_BUILD_SERVER
 | 
			
		||||
	BUILD_TARGETS += server
 | 
			
		||||
	LLAMA_SERVER_VERBOSE ?= 1
 | 
			
		||||
server: private CXXFLAGS += -DSERVER_VERBOSE=$(LLAMA_SERVER_VERBOSE)
 | 
			
		||||
endif
 | 
			
		||||
BUILD_TARGETS = main quantize quantize-stats perplexity embedding vdot train-text-from-scratch simple server libembdinput.so embd-input-test
 | 
			
		||||
 | 
			
		||||
default: $(BUILD_TARGETS)
 | 
			
		||||
 | 
			
		||||
@@ -61,6 +55,10 @@ else
 | 
			
		||||
	CXXFLAGS += -DNDEBUG
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifdef LLAMA_SERVER_VERBOSE
 | 
			
		||||
	CXXFLAGS += -DSERVER_VERBOSE=$(LLAMA_SERVER_VERBOSE)
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# warnings
 | 
			
		||||
CFLAGS   += -Wall -Wextra -Wpedantic -Wcast-qual -Wdouble-promotion -Wshadow -Wstrict-prototypes -Wpointer-arith
 | 
			
		||||
CXXFLAGS += -Wall -Wextra -Wpedantic -Wcast-qual -Wno-unused-function -Wno-multichar
 | 
			
		||||
@@ -272,7 +270,7 @@ libllama.so: llama.o ggml.o $(OBJS)
 | 
			
		||||
	$(CXX) $(CXXFLAGS) -shared -fPIC -o $@ $^ $(LDFLAGS)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -vf *.o *.so main quantize quantize-stats perplexity embedding benchmark-matmult save-load-state server vdot train-text-from-scratch embd-input-test build-info.h
 | 
			
		||||
	rm -vf *.o *.so main quantize quantize-stats perplexity embedding benchmark-matmult save-load-state server simple vdot train-text-from-scratch embd-input-test build-info.h
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# Examples
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ struct gpt_params {
 | 
			
		||||
    int32_t n_gpu_layers                    = 0;   // number of layers to store in VRAM
 | 
			
		||||
    int32_t main_gpu                        = 0;   // the GPU that is used for scratch and small tensors
 | 
			
		||||
    float   tensor_split[LLAMA_MAX_DEVICES] = {0}; // how split tensors should be distributed across GPUs
 | 
			
		||||
    bool    low_vram                        = 0;   // if true, reduce VRAM usage at the cost of performance
 | 
			
		||||
    int32_t n_probs                         = 0;   // if greater than 0, output the probabilities of top n_probs tokens.
 | 
			
		||||
 | 
			
		||||
    // sampling parameters
 | 
			
		||||
    std::unordered_map<llama_token, float> logit_bias; // logit bias for specific tokens
 | 
			
		||||
@@ -59,6 +59,7 @@ struct gpt_params {
 | 
			
		||||
    std::string lora_adapter = "";  // lora adapter path
 | 
			
		||||
    std::string lora_base    = "";  // base model path for the lora adapter
 | 
			
		||||
 | 
			
		||||
    bool low_vram          = false;   // if true, reduce VRAM usage at the cost of performance
 | 
			
		||||
    bool memory_f16        = true;  // use f16 instead of f32 for memory kv
 | 
			
		||||
    bool random_prompt     = false; // do not randomize prompt if none provided
 | 
			
		||||
    bool use_color         = false; // use color to distinguish generations and inputs
 | 
			
		||||
 
 | 
			
		||||
@@ -190,3 +190,19 @@ Run with bash:
 | 
			
		||||
```sh
 | 
			
		||||
bash chat.sh
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### API like OAI
 | 
			
		||||
 | 
			
		||||
API example using Python Flask: [api_like_OAI.py](api_like_OAI.py)
 | 
			
		||||
This example must be used with server.cpp
 | 
			
		||||
 | 
			
		||||
```sh
 | 
			
		||||
python api_like_OAI.py
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
After running the API server, you can use it in Python by setting the API base URL.
 | 
			
		||||
```python
 | 
			
		||||
openai.api_base = "http://<Your api-server IP>:port"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Then you can utilize llama.cpp as an OpenAI's **chat.completion** or **text_completion** API
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										219
									
								
								examples/server/api_like_OAI.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										219
									
								
								examples/server/api_like_OAI.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,219 @@
 | 
			
		||||
import argparse
 | 
			
		||||
from flask import Flask, jsonify, request, Response
 | 
			
		||||
import urllib.parse
 | 
			
		||||
import requests
 | 
			
		||||
import time
 | 
			
		||||
import json
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app = Flask(__name__)
 | 
			
		||||
 | 
			
		||||
parser = argparse.ArgumentParser(description="An example of using server.cpp with a similar API to OAI. It must be used together with server.cpp.")
 | 
			
		||||
parser.add_argument("--chat-prompt", type=str, help="the top prompt in chat completions(default: 'A chat between a curious user and an artificial intelligence assistant. The assistant follows the given rules no matter what.\\n')", default='A chat between a curious user and an artificial intelligence assistant. The assistant follows the given rules no matter what.\\n')
 | 
			
		||||
parser.add_argument("--user-name", type=str, help="USER name in chat completions(default: '\\nUSER: ')", default="\\nUSER: ")
 | 
			
		||||
parser.add_argument("--ai-name", type=str, help="ASSISTANT name in chat completions(default: '\\nASSISTANT: ')", default="\\nASSISTANT: ")
 | 
			
		||||
parser.add_argument("--system-name", type=str, help="SYSTEM name in chat completions(default: '\\nASSISTANT's RULE: ')", default="\\nASSISTANT's RULE: ")
 | 
			
		||||
parser.add_argument("--stop", type=str, help="the end of response in chat completions(default: '</s>')", default="</s>")
 | 
			
		||||
parser.add_argument("--llama-api", type=str, help="Set the address of server.cpp in llama.cpp(default: http://127.0.0.1:8080)", default='http://127.0.0.1:8080')
 | 
			
		||||
parser.add_argument("--api-key", type=str, help="Set the api key to allow only few user(default: NULL)", default="")
 | 
			
		||||
parser.add_argument("--host", type=str, help="Set the ip address to listen.(default: 127.0.0.1)", default='127.0.0.1')
 | 
			
		||||
parser.add_argument("--port", type=int, help="Set the port to listen.(default: 8081)", default=8081)
 | 
			
		||||
 | 
			
		||||
args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
def is_present(json, key):
 | 
			
		||||
    try:
 | 
			
		||||
        buf = json[key]
 | 
			
		||||
    except KeyError:
 | 
			
		||||
        return False
 | 
			
		||||
    return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#convert chat to prompt
 | 
			
		||||
def convert_chat(messages):
 | 
			
		||||
    prompt = "" + args.chat_prompt.replace("\\n", "\n")
 | 
			
		||||
 | 
			
		||||
    system_n = args.system_name.replace("\\n", "\n")
 | 
			
		||||
    user_n = args.user_name.replace("\\n", "\n")
 | 
			
		||||
    ai_n = args.ai_name.replace("\\n", "\n")
 | 
			
		||||
    stop = args.stop.replace("\\n", "\n")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    for line in messages:
 | 
			
		||||
        if (line["role"] == "system"):
 | 
			
		||||
            prompt += f"{system_n}{line['content']}"
 | 
			
		||||
        if (line["role"] == "user"):
 | 
			
		||||
            prompt += f"{user_n}{line['content']}"
 | 
			
		||||
        if (line["role"] == "assistant"):
 | 
			
		||||
            prompt += f"{ai_n}{line['content']}{stop}"
 | 
			
		||||
    prompt += ai_n.rstrip()
 | 
			
		||||
 | 
			
		||||
    return prompt
 | 
			
		||||
 | 
			
		||||
def make_postData(body, chat=False, stream=False):
 | 
			
		||||
    postData = {}
 | 
			
		||||
    if (chat):
 | 
			
		||||
        postData["prompt"] = convert_chat(body["messages"])
 | 
			
		||||
    else:
 | 
			
		||||
        postData["prompt"] = body["prompt"]
 | 
			
		||||
    if(is_present(body, "temperature")): postData["temperature"] = body["temperature"]
 | 
			
		||||
    if(is_present(body, "top_k")): postData["top_k"] = body["top_k"]
 | 
			
		||||
    if(is_present(body, "top_p")): postData["top_p"] = body["top_p"]
 | 
			
		||||
    if(is_present(body, "max_tokens")): postData["n_predict"] = body["max_tokens"]
 | 
			
		||||
    if(is_present(body, "presence_penalty")): postData["presence_penalty"] = body["presence_penalty"]
 | 
			
		||||
    if(is_present(body, "frequency_penalty")): postData["frequency_penalty"] = body["frequency_penalty"]
 | 
			
		||||
    if(is_present(body, "repeat_penalty")): postData["repeat_penalty"] = body["repeat_penalty"]
 | 
			
		||||
    if(is_present(body, "mirostat")): postData["mirostat"] = body["mirostat"]
 | 
			
		||||
    if(is_present(body, "mirostat_tau")): postData["mirostat_tau"] = body["mirostat_tau"]
 | 
			
		||||
    if(is_present(body, "mirostat_eta")): postData["mirostat_eta"] = body["mirostat_eta"]
 | 
			
		||||
    if(is_present(body, "seed")): postData["seed"] = body["seed"]
 | 
			
		||||
    if(is_present(body, "logit_bias")): postData["logit_bias"] = [[int(token), body["logit_bias"][token]] for token in body["logit_bias"].keys()]
 | 
			
		||||
    if (args.stop != ""):
 | 
			
		||||
        postData["stop"] = [args.stop]
 | 
			
		||||
    else:
 | 
			
		||||
        postData["stop"] = []
 | 
			
		||||
    if(is_present(body, "stop")): postData["stop"] += body["stop"]
 | 
			
		||||
    postData["n_keep"] = -1
 | 
			
		||||
    postData["stream"] = stream
 | 
			
		||||
 | 
			
		||||
    return postData
 | 
			
		||||
 | 
			
		||||
def make_resData(data, chat=False, promptToken=[]):
 | 
			
		||||
    resData = {
 | 
			
		||||
        "id": "chatcmpl" if (chat) else "cmpl",
 | 
			
		||||
        "object": "chat.completion" if (chat) else "text_completion",
 | 
			
		||||
        "created": int(time.time()),
 | 
			
		||||
        "truncated": data["truncated"],
 | 
			
		||||
        "model": "LLaMA_CPP",
 | 
			
		||||
        "usage": {
 | 
			
		||||
            "prompt_tokens": data["tokens_evaluated"],
 | 
			
		||||
            "completion_tokens": data["tokens_predicted"],
 | 
			
		||||
            "total_tokens": data["tokens_evaluated"] + data["tokens_predicted"]
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (len(promptToken) != 0):
 | 
			
		||||
        resData["promptToken"] = promptToken
 | 
			
		||||
    if (chat):
 | 
			
		||||
        #only one choice is supported
 | 
			
		||||
        resData["choices"] = [{
 | 
			
		||||
            "index": 0,
 | 
			
		||||
            "message": {
 | 
			
		||||
                "role": "assistant",
 | 
			
		||||
                "content": data["content"],
 | 
			
		||||
            },
 | 
			
		||||
            "finish_reason": "stop" if (data["stopped_eos"] or data["stopped_word"]) else "length"
 | 
			
		||||
        }]
 | 
			
		||||
    else:
 | 
			
		||||
        #only one choice is supported
 | 
			
		||||
        resData["choices"] = [{
 | 
			
		||||
            "text": data["content"],
 | 
			
		||||
            "index": 0,
 | 
			
		||||
            "logprobs": None,
 | 
			
		||||
            "finish_reason": "stop" if (data["stopped_eos"] or data["stopped_word"]) else "length"
 | 
			
		||||
        }]
 | 
			
		||||
    return resData
 | 
			
		||||
 | 
			
		||||
def make_resData_stream(data, chat=False, time_now = 0, start=False):
 | 
			
		||||
    resData = {
 | 
			
		||||
        "id": "chatcmpl" if (chat) else "cmpl",
 | 
			
		||||
        "object": "chat.completion.chunk" if (chat) else "text_completion.chunk",
 | 
			
		||||
        "created": time_now,
 | 
			
		||||
        "model": "LLaMA_CPP",
 | 
			
		||||
        "choices": [
 | 
			
		||||
            {
 | 
			
		||||
                "finish_reason": None,
 | 
			
		||||
                "index": 0
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    }
 | 
			
		||||
    if (chat):
 | 
			
		||||
        if (start):
 | 
			
		||||
            resData["choices"][0]["delta"] =  {
 | 
			
		||||
                "role": "assistant"
 | 
			
		||||
            }
 | 
			
		||||
        else:
 | 
			
		||||
            resData["choices"][0]["delta"] =  {
 | 
			
		||||
                "content": data["content"]
 | 
			
		||||
            }
 | 
			
		||||
            if (data["stop"]):
 | 
			
		||||
                resData["choices"][0]["finish_reason"] = "stop" if (data["stopped_eos"] or data["stopped_word"]) else "length"
 | 
			
		||||
    else:
 | 
			
		||||
        resData["choices"][0]["text"] = data["content"]
 | 
			
		||||
        if (data["stop"]):
 | 
			
		||||
            resData["choices"][0]["finish_reason"] = "stop" if (data["stopped_eos"] or data["stopped_word"]) else "length"
 | 
			
		||||
 | 
			
		||||
    return resData
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@app.route('/chat/completions', methods=['POST'])
 | 
			
		||||
@app.route('/v1/chat/completions', methods=['POST'])
 | 
			
		||||
def chat_completions():
 | 
			
		||||
    if (args.api_key != "" and request.headers["Authorization"].split()[1] != args.api_key):
 | 
			
		||||
        return Response(status=403)
 | 
			
		||||
    body = request.get_json()
 | 
			
		||||
    stream = False
 | 
			
		||||
    tokenize = False
 | 
			
		||||
    if(is_present(body, "stream")): stream = body["stream"]
 | 
			
		||||
    if(is_present(body, "tokenize")): tokenize = body["tokenize"]
 | 
			
		||||
    postData = make_postData(body, chat=True, stream=stream)
 | 
			
		||||
 | 
			
		||||
    promptToken = []
 | 
			
		||||
    if (tokenize):
 | 
			
		||||
        tokenData = requests.request("POST", urllib.parse.urljoin(args.llama_api, "/tokenize"), data=json.dumps({"content": postData["prompt"]})).json()
 | 
			
		||||
        promptToken = tokenData["tokens"]
 | 
			
		||||
 | 
			
		||||
    if (not stream):
 | 
			
		||||
        data = requests.request("POST", urllib.parse.urljoin(args.llama_api, "/completion"), data=json.dumps(postData))
 | 
			
		||||
        print(data.json())
 | 
			
		||||
        resData = make_resData(data.json(), chat=True, promptToken=promptToken)
 | 
			
		||||
        return jsonify(resData)
 | 
			
		||||
    else:
 | 
			
		||||
        def generate():
 | 
			
		||||
            data = requests.request("POST", urllib.parse.urljoin(args.llama_api, "/completion"), data=json.dumps(postData), stream=True)
 | 
			
		||||
            time_now = int(time.time())
 | 
			
		||||
            resData = make_resData_stream({}, chat=True, time_now=time_now, start=True)
 | 
			
		||||
            yield 'data: {}\n'.format(json.dumps(resData))
 | 
			
		||||
            for line in data.iter_lines():
 | 
			
		||||
                if line:
 | 
			
		||||
                    decoded_line = line.decode('utf-8')
 | 
			
		||||
                    resData = make_resData_stream(json.loads(decoded_line[6:]), chat=True, time_now=time_now)
 | 
			
		||||
                    yield 'data: {}\n'.format(json.dumps(resData))
 | 
			
		||||
        return Response(generate(), mimetype='text/event-stream')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@app.route('/completions', methods=['POST'])
 | 
			
		||||
@app.route('/v1/completions', methods=['POST'])
 | 
			
		||||
def completion():
 | 
			
		||||
    if (args.api_key != "" and request.headers["Authorization"].split()[1] != args.api_key):
 | 
			
		||||
        return Response(status=403)
 | 
			
		||||
    body = request.get_json()
 | 
			
		||||
    stream = False
 | 
			
		||||
    tokenize = False
 | 
			
		||||
    if(is_present(body, "stream")): stream = body["stream"]
 | 
			
		||||
    if(is_present(body, "tokenize")): tokenize = body["tokenize"]
 | 
			
		||||
    postData = make_postData(body, chat=False, stream=stream)
 | 
			
		||||
 | 
			
		||||
    promptToken = []
 | 
			
		||||
    if (tokenize):
 | 
			
		||||
        tokenData = requests.request("POST", urllib.parse.urljoin(args.llama_api, "/tokenize"), data=json.dumps({"content": postData["prompt"]})).json()
 | 
			
		||||
        promptToken = tokenData["tokens"]
 | 
			
		||||
 | 
			
		||||
    if (not stream):
 | 
			
		||||
        data = requests.request("POST", urllib.parse.urljoin(args.llama_api, "/completion"), data=json.dumps(postData))
 | 
			
		||||
        print(data.json())
 | 
			
		||||
        resData = make_resData(data.json(), chat=False, promptToken=promptToken)
 | 
			
		||||
        return jsonify(resData)
 | 
			
		||||
    else:
 | 
			
		||||
        def generate():
 | 
			
		||||
            data = requests.request("POST", urllib.parse.urljoin(args.llama_api, "/completion"), data=json.dumps(postData), stream=True)
 | 
			
		||||
            time_now = int(time.time())
 | 
			
		||||
            for line in data.iter_lines():
 | 
			
		||||
                if line:
 | 
			
		||||
                    decoded_line = line.decode('utf-8')
 | 
			
		||||
                    resData = make_resData_stream(json.loads(decoded_line[6:]), chat=False, time_now=time_now)
 | 
			
		||||
                    yield 'data: {}\n'.format(json.dumps(resData))
 | 
			
		||||
        return Response(generate(), mimetype='text/event-stream')
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    app.run(args.host, port=args.port)
 | 
			
		||||
							
								
								
									
										193
									
								
								examples/server/completion.js.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								examples/server/completion.js.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,193 @@
 | 
			
		||||
unsigned char completion_js[] = {
 | 
			
		||||
  0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x44,
 | 
			
		||||
  0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x3a, 0x20, 0x74, 0x72,
 | 
			
		||||
  0x75, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x64,
 | 
			
		||||
  0x69, 0x63, 0x74, 0x3a, 0x20, 0x35, 0x30, 0x30, 0x2c, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x74, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3a,
 | 
			
		||||
  0x20, 0x30, 0x2e, 0x32, 0x2c, 0x0a, 0x20, 0x20, 0x73, 0x74, 0x6f, 0x70,
 | 
			
		||||
  0x3a, 0x20, 0x5b, 0x22, 0x3c, 0x2f, 0x73, 0x3e, 0x22, 0x5d, 0x0a, 0x7d,
 | 
			
		||||
  0x3b, 0x0a, 0x0a, 0x2f, 0x2a, 0x2a, 0x0a, 0x20, 0x2a, 0x20, 0x54, 0x68,
 | 
			
		||||
  0x69, 0x73, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20,
 | 
			
		||||
  0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68,
 | 
			
		||||
  0x65, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74,
 | 
			
		||||
  0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c, 0x6c, 0x61,
 | 
			
		||||
  0x6d, 0x61, 0x20, 0x64, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x72,
 | 
			
		||||
  0x79, 0x2e, 0x0a, 0x20, 0x2a, 0x20, 0x40, 0x70, 0x61, 0x72, 0x61, 0x6d,
 | 
			
		||||
  0x20, 0x7b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x7d, 0x20, 0x70, 0x61,
 | 
			
		||||
  0x72, 0x61, 0x6d, 0x73, 0x20, 0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x70,
 | 
			
		||||
  0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x66, 0x6f,
 | 
			
		||||
  0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
 | 
			
		||||
  0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
 | 
			
		||||
  0x2e, 0x0a, 0x20, 0x2a, 0x20, 0x40, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x20,
 | 
			
		||||
  0x7b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x7d, 0x20, 0x63, 0x6f, 0x6e,
 | 
			
		||||
  0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x2d, 0x20, 0x61, 0x6e,
 | 
			
		||||
  0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x6f, 0x66,
 | 
			
		||||
  0x20, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
 | 
			
		||||
  0x6c, 0x6c, 0x65, 0x72, 0x20, 0x69, 0x66, 0x20, 0x79, 0x6f, 0x75, 0x20,
 | 
			
		||||
  0x6e, 0x65, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x65, 0x2c, 0x20, 0x6f, 0x72,
 | 
			
		||||
  0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x2e, 0x0a, 0x20, 0x2a, 0x20, 0x40, 0x70,
 | 
			
		||||
  0x61, 0x72, 0x61, 0x6d, 0x20, 0x7b, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
 | 
			
		||||
  0x6f, 0x6e, 0x7d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
 | 
			
		||||
  0x20, 0x2d, 0x20, 0x54, 0x68, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62,
 | 
			
		||||
  0x61, 0x63, 0x6b, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
 | 
			
		||||
  0x20, 0x74, 0x6f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x77, 0x68, 0x65,
 | 
			
		||||
  0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
 | 
			
		||||
  0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x6e, 0x65,
 | 
			
		||||
  0x2e, 0x0a, 0x20, 0x2a, 0x20, 0x40, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
 | 
			
		||||
  0x73, 0x20, 0x7b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x7d, 0x20, 0x74,
 | 
			
		||||
  0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64,
 | 
			
		||||
  0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x73,
 | 
			
		||||
  0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x20, 0x49, 0x64, 0x65, 0x61, 0x6c,
 | 
			
		||||
  0x6c, 0x79, 0x20, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x2c, 0x20,
 | 
			
		||||
  0x61, 0x6e, 0x64, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x67, 0x65, 0x74, 0x20,
 | 
			
		||||
  0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x76, 0x69, 0x61, 0x20, 0x74, 0x68,
 | 
			
		||||
  0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x2e, 0x0a,
 | 
			
		||||
  0x20, 0x2a, 0x2f, 0x0a, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x63,
 | 
			
		||||
  0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x43, 0x6f,
 | 
			
		||||
  0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x79,
 | 
			
		||||
  0x6e, 0x63, 0x20, 0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20,
 | 
			
		||||
  0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2c, 0x20,
 | 
			
		||||
  0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x29, 0x20, 0x3d, 0x3e,
 | 
			
		||||
  0x20, 0x7b, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x21, 0x63, 0x6f,
 | 
			
		||||
  0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x29, 0x20, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
 | 
			
		||||
  0x65, 0x72, 0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x41, 0x62, 0x6f,
 | 
			
		||||
  0x72, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
 | 
			
		||||
  0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x63, 0x6f,
 | 
			
		||||
  0x6e, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69,
 | 
			
		||||
  0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x3d, 0x20, 0x7b,
 | 
			
		||||
  0x20, 0x2e, 0x2e, 0x2e, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x44, 0x65, 0x66,
 | 
			
		||||
  0x61, 0x75, 0x6c, 0x74, 0x73, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x70, 0x61,
 | 
			
		||||
  0x72, 0x61, 0x6d, 0x73, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x2f,
 | 
			
		||||
  0x2f, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x66, 0x65, 0x74,
 | 
			
		||||
  0x63, 0x68, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x20,
 | 
			
		||||
  0x68, 0x65, 0x72, 0x65, 0x20, 0x62, 0x65, 0x63, 0x61, 0x73, 0x75, 0x65,
 | 
			
		||||
  0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 0x69,
 | 
			
		||||
  0x6e, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74,
 | 
			
		||||
  0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20,
 | 
			
		||||
  0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x20,
 | 
			
		||||
  0x50, 0x4f, 0x53, 0x54, 0x0a, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
 | 
			
		||||
  0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x20, 0x3d, 0x20,
 | 
			
		||||
  0x61, 0x77, 0x61, 0x69, 0x74, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x28,
 | 
			
		||||
  0x22, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e,
 | 
			
		||||
  0x22, 0x2c, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, 0x74,
 | 
			
		||||
  0x68, 0x6f, 0x64, 0x3a, 0x20, 0x27, 0x50, 0x4f, 0x53, 0x54, 0x27, 0x2c,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x20, 0x4a,
 | 
			
		||||
  0x53, 0x4f, 0x4e, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x66,
 | 
			
		||||
  0x79, 0x28, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e,
 | 
			
		||||
  0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x2c, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x20, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x43, 0x6f, 0x6e, 0x6e, 0x65,
 | 
			
		||||
  0x63, 0x74, 0x69, 0x6f, 0x6e, 0x27, 0x3a, 0x20, 0x27, 0x6b, 0x65, 0x65,
 | 
			
		||||
  0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x27, 0x2c, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x27, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
 | 
			
		||||
  0x2d, 0x54, 0x79, 0x70, 0x65, 0x27, 0x3a, 0x20, 0x27, 0x61, 0x70, 0x70,
 | 
			
		||||
  0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f,
 | 
			
		||||
  0x6e, 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x41,
 | 
			
		||||
  0x63, 0x63, 0x65, 0x70, 0x74, 0x27, 0x3a, 0x20, 0x27, 0x74, 0x65, 0x78,
 | 
			
		||||
  0x74, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x74, 0x72, 0x65,
 | 
			
		||||
  0x61, 0x6d, 0x27, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x2c, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x3a, 0x20, 0x63,
 | 
			
		||||
  0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x69,
 | 
			
		||||
  0x67, 0x6e, 0x61, 0x6c, 0x2c, 0x0a, 0x20, 0x20, 0x7d, 0x29, 0x3b, 0x0a,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x72, 0x65, 0x61,
 | 
			
		||||
  0x64, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e,
 | 
			
		||||
  0x73, 0x65, 0x2e, 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x67, 0x65, 0x74, 0x52,
 | 
			
		||||
  0x65, 0x61, 0x64, 0x65, 0x72, 0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x63,
 | 
			
		||||
  0x6f, 0x6e, 0x73, 0x74, 0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x54, 0x65, 0x78, 0x74, 0x44,
 | 
			
		||||
  0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x28, 0x29, 0x3b, 0x0a, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x6c, 0x65, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x22, 0x22, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x74, 0x72,
 | 
			
		||||
  0x79, 0x20, 0x7b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74,
 | 
			
		||||
  0x20, 0x63, 0x6f, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65,
 | 
			
		||||
  0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65,
 | 
			
		||||
  0x20, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x72, 0x65,
 | 
			
		||||
  0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x61, 0x77, 0x61, 0x69, 0x74,
 | 
			
		||||
  0x20, 0x72, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x72, 0x65, 0x61, 0x64,
 | 
			
		||||
  0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
 | 
			
		||||
  0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x64, 0x6f, 0x6e,
 | 
			
		||||
  0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f,
 | 
			
		||||
  0x2f, 0x20, 0x73, 0x73, 0x65, 0x20, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72,
 | 
			
		||||
  0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x72,
 | 
			
		||||
  0x6d, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x6c,
 | 
			
		||||
  0x69, 0x6e, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x3a, 0x20, 0x76, 0x61, 0x6c,
 | 
			
		||||
  0x75, 0x65, 0x5c, 0x6e, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x64, 0x61,
 | 
			
		||||
  0x74, 0x61, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x70, 0x72,
 | 
			
		||||
  0x65, 0x73, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x73, 0x20, 0x61, 0x20, 0x6b,
 | 
			
		||||
  0x65, 0x79, 0x2e, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x75, 0x72, 0x20, 0x63,
 | 
			
		||||
  0x61, 0x73, 0x65, 0x20, 0x77, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x2f, 0x2f, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x6c, 0x79, 0x20, 0x63,
 | 
			
		||||
  0x61, 0x72, 0x65, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x74, 0x68,
 | 
			
		||||
  0x65, 0x20, 0x64, 0x61, 0x74, 0x61, 0x3a, 0x20, 0x6b, 0x65, 0x79, 0x20,
 | 
			
		||||
  0x68, 0x65, 0x72, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20,
 | 
			
		||||
  0x77, 0x65, 0x20, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x20, 0x61, 0x73,
 | 
			
		||||
  0x20, 0x6a, 0x73, 0x6f, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x74, 0x65, 0x78, 0x74, 0x20, 0x3d,
 | 
			
		||||
  0x20, 0x64, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x64, 0x65, 0x63,
 | 
			
		||||
  0x6f, 0x64, 0x65, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x76,
 | 
			
		||||
  0x61, 0x6c, 0x75, 0x65, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x2f, 0x2f, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x20, 0x61,
 | 
			
		||||
  0x6c, 0x6c, 0x20, 0x73, 0x73, 0x65, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74,
 | 
			
		||||
  0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x64, 0x64, 0x20, 0x74, 0x68,
 | 
			
		||||
  0x65, 0x6d, 0x20, 0x74, 0x6f, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
 | 
			
		||||
  0x20, 0x72, 0x65, 0x67, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x2f, 0x5e, 0x28,
 | 
			
		||||
  0x5c, 0x53, 0x2b, 0x29, 0x3a, 0x5c, 0x73, 0x28, 0x2e, 0x2a, 0x29, 0x24,
 | 
			
		||||
  0x2f, 0x67, 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66,
 | 
			
		||||
  0x6f, 0x72, 0x20, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6d, 0x61,
 | 
			
		||||
  0x74, 0x63, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x65, 0x78, 0x74, 0x2e,
 | 
			
		||||
  0x6d, 0x61, 0x74, 0x63, 0x68, 0x41, 0x6c, 0x6c, 0x28, 0x72, 0x65, 0x67,
 | 
			
		||||
  0x65, 0x78, 0x29, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5b, 0x6d, 0x61,
 | 
			
		||||
  0x74, 0x63, 0x68, 0x5b, 0x31, 0x5d, 0x5d, 0x20, 0x3d, 0x20, 0x6d, 0x61,
 | 
			
		||||
  0x74, 0x63, 0x68, 0x5b, 0x32, 0x5d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f,
 | 
			
		||||
  0x20, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x20, 0x77, 0x65, 0x20, 0x6b, 0x6e,
 | 
			
		||||
  0x6f, 0x77, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6c,
 | 
			
		||||
  0x6c, 0x61, 0x6d, 0x61, 0x2e, 0x63, 0x70, 0x70, 0x2c, 0x20, 0x6c, 0x65,
 | 
			
		||||
  0x74, 0x27, 0x73, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x64, 0x65, 0x63,
 | 
			
		||||
  0x6f, 0x64, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6a, 0x73, 0x6f, 0x6e,
 | 
			
		||||
  0x20, 0x69, 0x6e, 0x20, 0x64, 0x61, 0x74, 0x61, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x64, 0x61,
 | 
			
		||||
  0x74, 0x61, 0x20, 0x3d, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x2e, 0x70, 0x61,
 | 
			
		||||
  0x72, 0x73, 0x65, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x64,
 | 
			
		||||
  0x61, 0x74, 0x61, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x20, 0x2b, 0x3d, 0x20, 0x72,
 | 
			
		||||
  0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x63,
 | 
			
		||||
  0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x61, 0x63,
 | 
			
		||||
  0x6b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
 | 
			
		||||
  0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x29, 0x20, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x28,
 | 
			
		||||
  0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x66,
 | 
			
		||||
  0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20,
 | 
			
		||||
  0x69, 0x66, 0x20, 0x77, 0x65, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x61, 0x20,
 | 
			
		||||
  0x73, 0x74, 0x6f, 0x70, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x20, 0x66,
 | 
			
		||||
  0x72, 0x6f, 0x6d, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2c, 0x20,
 | 
			
		||||
  0x77, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x72, 0x65, 0x61,
 | 
			
		||||
  0x6b, 0x20, 0x68, 0x65, 0x72, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x69, 0x66, 0x20, 0x28, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e,
 | 
			
		||||
  0x64, 0x61, 0x74, 0x61, 0x2e, 0x73, 0x74, 0x6f, 0x70, 0x29, 0x20, 0x7b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x72, 0x65,
 | 
			
		||||
  0x61, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x20, 0x63, 0x61,
 | 
			
		||||
  0x74, 0x63, 0x68, 0x20, 0x28, 0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x65, 0x72,
 | 
			
		||||
  0x72, 0x6f, 0x72, 0x28, 0x22, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x20, 0x65,
 | 
			
		||||
  0x72, 0x72, 0x6f, 0x72, 0x3a, 0x20, 0x22, 0x2c, 0x20, 0x65, 0x29, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x74, 0x68, 0x72, 0x6f, 0x77, 0x20, 0x65,
 | 
			
		||||
  0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x66, 0x69, 0x6e, 0x61,
 | 
			
		||||
  0x6c, 0x6c, 0x79, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
 | 
			
		||||
  0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x62, 0x6f,
 | 
			
		||||
  0x72, 0x74, 0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74,
 | 
			
		||||
  0x65, 0x6e, 0x74, 0x3b, 0x0a, 0x7d, 0x0a
 | 
			
		||||
};
 | 
			
		||||
unsigned int completion_js_len = 2275;
 | 
			
		||||
							
								
								
									
										22
									
								
								examples/server/deps.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								examples/server/deps.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
# Download and update deps for binary
 | 
			
		||||
 | 
			
		||||
# get the directory of this script file
 | 
			
		||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
 | 
			
		||||
PUBLIC=$DIR/public
 | 
			
		||||
OUTPUT=$DIR/templats.hpp
 | 
			
		||||
 | 
			
		||||
echo "// Generated file, do not edit" > $OUTPUT
 | 
			
		||||
echo "" > $OUTPUT
 | 
			
		||||
 | 
			
		||||
echo "download js bundle files"
 | 
			
		||||
curl https://npm.reversehttp.com/@preact/signals-core,@preact/signals,htm/preact,preact,preact/hooks > $PUBLIC/index.js
 | 
			
		||||
echo >> $PUBLIC/index.js # add newline
 | 
			
		||||
 | 
			
		||||
FILES=$(ls $PUBLIC)
 | 
			
		||||
 | 
			
		||||
for FILE in $FILES; do
 | 
			
		||||
  func=$(echo $FILE | tr '.' '_')
 | 
			
		||||
  echo "generate $FILE.hpp ($func)"
 | 
			
		||||
  xxd -n $func -i $PUBLIC/$FILE > $DIR/$FILE.hpp
 | 
			
		||||
done
 | 
			
		||||
							
								
								
									
										846
									
								
								examples/server/index.html.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										846
									
								
								examples/server/index.html.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,846 @@
 | 
			
		||||
unsigned char index_html[] = {
 | 
			
		||||
  0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x0a, 0x0a, 0x3c, 0x68, 0x65, 0x61,
 | 
			
		||||
  0x64, 0x3e, 0x0a, 0x20, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20, 0x63,
 | 
			
		||||
  0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d,
 | 
			
		||||
  0x38, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x3c, 0x6d, 0x65, 0x74, 0x61, 0x20,
 | 
			
		||||
  0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x65, 0x77, 0x70, 0x6f,
 | 
			
		||||
  0x72, 0x74, 0x22, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3d,
 | 
			
		||||
  0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x64, 0x65, 0x76, 0x69, 0x63,
 | 
			
		||||
  0x65, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2c, 0x20, 0x69, 0x6e, 0x69,
 | 
			
		||||
  0x74, 0x69, 0x61, 0x6c, 0x2d, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x3d, 0x31,
 | 
			
		||||
  0x2c, 0x20, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x2d, 0x73, 0x63,
 | 
			
		||||
  0x61, 0x6c, 0x65, 0x3d, 0x31, 0x22, 0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x6c, 0x6c, 0x61, 0x6d, 0x61,
 | 
			
		||||
  0x2e, 0x63, 0x70, 0x70, 0x20, 0x2d, 0x20, 0x63, 0x68, 0x61, 0x74, 0x3c,
 | 
			
		||||
  0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x73, 0x74, 0x79, 0x6c, 0x65, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x62, 0x6f, 0x64, 0x79, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x2d,
 | 
			
		||||
  0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x66, 0x66, 0x66, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
 | 
			
		||||
  0x3a, 0x20, 0x23, 0x30, 0x30, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c,
 | 
			
		||||
  0x79, 0x3a, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2d, 0x75, 0x69,
 | 
			
		||||
  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74,
 | 
			
		||||
  0x2d, 0x73, 0x69, 0x7a, 0x65, 0x3a, 0x20, 0x39, 0x30, 0x25, 0x3b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x23,
 | 
			
		||||
  0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x20, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e,
 | 
			
		||||
  0x3a, 0x20, 0x30, 0x65, 0x6d, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61,
 | 
			
		||||
  0x79, 0x3a, 0x20, 0x66, 0x6c, 0x65, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x66, 0x6c, 0x65, 0x78, 0x2d, 0x64, 0x69, 0x72, 0x65,
 | 
			
		||||
  0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d,
 | 
			
		||||
  0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6a, 0x75, 0x73,
 | 
			
		||||
  0x74, 0x69, 0x66, 0x79, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
 | 
			
		||||
  0x3a, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2d, 0x62, 0x65, 0x74, 0x77,
 | 
			
		||||
  0x65, 0x65, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68,
 | 
			
		||||
  0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2c, 0x20, 0x66, 0x6f, 0x6f, 0x74,
 | 
			
		||||
  0x65, 0x72, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
 | 
			
		||||
  0x65, 0x78, 0x74, 0x2d, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3a, 0x20, 0x63,
 | 
			
		||||
  0x65, 0x6e, 0x74, 0x65, 0x72, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
 | 
			
		||||
  0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x7b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69,
 | 
			
		||||
  0x6e, 0x3a, 0x20, 0x33, 0x70, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x66,
 | 
			
		||||
  0x6c, 0x65, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66,
 | 
			
		||||
  0x6c, 0x65, 0x78, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f,
 | 
			
		||||
  0x6e, 0x3a, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x3b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x69, 0x66, 0x79,
 | 
			
		||||
  0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20, 0x73, 0x70,
 | 
			
		||||
  0x61, 0x63, 0x65, 0x2d, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x61, 0x70, 0x3a, 0x20,
 | 
			
		||||
  0x31, 0x65, 0x6d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x66, 0x6c, 0x65, 0x78, 0x2d, 0x67, 0x72, 0x6f, 0x77, 0x3a, 0x20, 0x31,
 | 
			
		||||
  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76, 0x65, 0x72,
 | 
			
		||||
  0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x79, 0x3a, 0x20, 0x61, 0x75, 0x74, 0x6f,
 | 
			
		||||
  0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72,
 | 
			
		||||
  0x64, 0x65, 0x72, 0x3a, 0x20, 0x31, 0x70, 0x78, 0x20, 0x73, 0x6f, 0x6c,
 | 
			
		||||
  0x69, 0x64, 0x20, 0x23, 0x63, 0x63, 0x63, 0x3b, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x72, 0x61,
 | 
			
		||||
  0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x35, 0x70, 0x78, 0x3b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67,
 | 
			
		||||
  0x3a, 0x20, 0x30, 0x2e, 0x35, 0x65, 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x64, 0x79,
 | 
			
		||||
  0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x78,
 | 
			
		||||
  0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x36, 0x30, 0x30, 0x70,
 | 
			
		||||
  0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x69, 0x6e,
 | 
			
		||||
  0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x33, 0x30, 0x30, 0x70,
 | 
			
		||||
  0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x69, 0x6e,
 | 
			
		||||
  0x65, 0x2d, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3a, 0x20, 0x31, 0x2e,
 | 
			
		||||
  0x32, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
 | 
			
		||||
  0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69,
 | 
			
		||||
  0x6e, 0x67, 0x3a, 0x20, 0x30, 0x20, 0x30, 0x2e, 0x35, 0x65, 0x6d, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x70, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x76,
 | 
			
		||||
  0x65, 0x72, 0x66, 0x6c, 0x6f, 0x77, 0x2d, 0x77, 0x72, 0x61, 0x70, 0x3a,
 | 
			
		||||
  0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x2d, 0x77, 0x6f, 0x72, 0x64, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x2d,
 | 
			
		||||
  0x77, 0x72, 0x61, 0x70, 0x3a, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x2d,
 | 
			
		||||
  0x77, 0x6f, 0x72, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x3a, 0x20, 0x61, 0x75, 0x74,
 | 
			
		||||
  0x6f, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72,
 | 
			
		||||
  0x67, 0x69, 0x6e, 0x2d, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x30, 0x2e, 0x35,
 | 
			
		||||
  0x65, 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61,
 | 
			
		||||
  0x72, 0x67, 0x69, 0x6e, 0x2d, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x3a,
 | 
			
		||||
  0x20, 0x30, 0x2e, 0x35, 0x65, 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x23, 0x77, 0x72, 0x69, 0x74,
 | 
			
		||||
  0x65, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x31,
 | 
			
		||||
  0x65, 0x6d, 0x20, 0x30, 0x20, 0x30, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
 | 
			
		||||
  0x20, 0x66, 0x6c, 0x65, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x66, 0x6c, 0x65, 0x78, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
 | 
			
		||||
  0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x61, 0x70, 0x3a, 0x20,
 | 
			
		||||
  0x30, 0x2e, 0x35, 0x65, 0x6d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x2d, 0x69, 0x74, 0x65, 0x6d, 0x73,
 | 
			
		||||
  0x3a, 0x20, 0x73, 0x74, 0x72, 0x65, 0x74, 0x63, 0x68, 0x3b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x72,
 | 
			
		||||
  0x69, 0x67, 0x68, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x66, 0x6c,
 | 
			
		||||
  0x65, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6c,
 | 
			
		||||
  0x65, 0x78, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e,
 | 
			
		||||
  0x3a, 0x20, 0x72, 0x6f, 0x77, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x67, 0x61, 0x70, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x65, 0x6d, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x69,
 | 
			
		||||
  0x66, 0x79, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x3a, 0x20,
 | 
			
		||||
  0x66, 0x6c, 0x65, 0x78, 0x2d, 0x65, 0x6e, 0x64, 0x3b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x65,
 | 
			
		||||
  0x6c, 0x64, 0x73, 0x65, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x20, 0x6e, 0x6f,
 | 
			
		||||
  0x6e, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61,
 | 
			
		||||
  0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20,
 | 
			
		||||
  0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x7b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69,
 | 
			
		||||
  0x6e, 0x67, 0x3a, 0x20, 0x35, 0x70, 0x78, 0x3b, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x66, 0x6c, 0x65, 0x78, 0x2d, 0x67, 0x72, 0x6f, 0x77,
 | 
			
		||||
  0x3a, 0x20, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77,
 | 
			
		||||
  0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70,
 | 
			
		||||
  0x72, 0x65, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20, 0x7b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a,
 | 
			
		||||
  0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x62, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
 | 
			
		||||
  0x2d, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3a, 0x20, 0x23, 0x32, 0x32, 0x32,
 | 
			
		||||
  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
 | 
			
		||||
  0x72, 0x3a, 0x20, 0x23, 0x64, 0x64, 0x64, 0x3b, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x20,
 | 
			
		||||
  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74,
 | 
			
		||||
  0x2d, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x3a, 0x20, 0x6d, 0x6f, 0x6e,
 | 
			
		||||
  0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3a, 0x20, 0x30,
 | 
			
		||||
  0x2e, 0x31, 0x65, 0x6d, 0x20, 0x30, 0x2e, 0x33, 0x65, 0x6d, 0x3b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72,
 | 
			
		||||
  0x2d, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x3a, 0x20, 0x33, 0x70, 0x78,
 | 
			
		||||
  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x65, 0x74, 0x20, 0x6c, 0x61,
 | 
			
		||||
  0x62, 0x65, 0x6c, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x3a, 0x20, 0x30, 0x2e, 0x35, 0x65,
 | 
			
		||||
  0x6d, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x64,
 | 
			
		||||
  0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x3a, 0x20, 0x62, 0x6c, 0x6f, 0x63,
 | 
			
		||||
  0x6b, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d,
 | 
			
		||||
  0x22, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x22, 0x3e, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x7b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x20, 0x68,
 | 
			
		||||
  0x2c, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x2c, 0x20, 0x65, 0x66,
 | 
			
		||||
  0x66, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74,
 | 
			
		||||
  0x65, 0x64, 0x2c, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x2c, 0x20,
 | 
			
		||||
  0x75, 0x73, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x2c, 0x20, 0x75,
 | 
			
		||||
  0x73, 0x65, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x75, 0x73,
 | 
			
		||||
  0x65, 0x52, 0x65, 0x66, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x20, 0x66,
 | 
			
		||||
  0x72, 0x6f, 0x6d, 0x20, 0x27, 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e,
 | 
			
		||||
  0x6a, 0x73, 0x27, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6d,
 | 
			
		||||
  0x70, 0x6f, 0x72, 0x74, 0x20, 0x7b, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61,
 | 
			
		||||
  0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x7d, 0x20, 0x66,
 | 
			
		||||
  0x72, 0x6f, 0x6d, 0x20, 0x27, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65,
 | 
			
		||||
  0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6a, 0x73, 0x27, 0x3b, 0x0a, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x73, 0x65, 0x73,
 | 
			
		||||
  0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61,
 | 
			
		||||
  0x6c, 0x28, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72,
 | 
			
		||||
  0x6f, 0x6d, 0x70, 0x74, 0x3a, 0x20, 0x22, 0x54, 0x68, 0x69, 0x73, 0x20,
 | 
			
		||||
  0x69, 0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73,
 | 
			
		||||
  0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65,
 | 
			
		||||
  0x6e, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c,
 | 
			
		||||
  0x6c, 0x61, 0x6d, 0x61, 0x2c, 0x20, 0x61, 0x20, 0x66, 0x72, 0x69, 0x65,
 | 
			
		||||
  0x6e, 0x64, 0x6c, 0x79, 0x20, 0x63, 0x68, 0x61, 0x74, 0x62, 0x6f, 0x74,
 | 
			
		||||
  0x2e, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x20, 0x69, 0x6e,
 | 
			
		||||
  0x20, 0x6d, 0x61, 0x72, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x2e, 0x22, 0x2c,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c,
 | 
			
		||||
  0x61, 0x74, 0x65, 0x3a, 0x20, 0x22, 0x7b, 0x7b, 0x70, 0x72, 0x6f, 0x6d,
 | 
			
		||||
  0x70, 0x74, 0x7d, 0x7d, 0x5c, 0x6e, 0x5c, 0x6e, 0x7b, 0x7b, 0x68, 0x69,
 | 
			
		||||
  0x73, 0x74, 0x6f, 0x72, 0x79, 0x7d, 0x7d, 0x5c, 0x6e, 0x7b, 0x7b, 0x63,
 | 
			
		||||
  0x68, 0x61, 0x72, 0x7d, 0x7d, 0x3a, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x65,
 | 
			
		||||
  0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3a, 0x20, 0x22, 0x7b, 0x7b, 0x6e,
 | 
			
		||||
  0x61, 0x6d, 0x65, 0x7d, 0x7d, 0x3a, 0x20, 0x7b, 0x7b, 0x6d, 0x65, 0x73,
 | 
			
		||||
  0x73, 0x61, 0x67, 0x65, 0x7d, 0x7d, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70,
 | 
			
		||||
  0x74, 0x3a, 0x20, 0x5b, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x22, 0x63, 0x68, 0x61, 0x74,
 | 
			
		||||
  0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x68, 0x61,
 | 
			
		||||
  0x72, 0x3a, 0x20, 0x22, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x22, 0x2c, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x75, 0x73, 0x65, 0x72, 0x3a, 0x20,
 | 
			
		||||
  0x22, 0x55, 0x73, 0x65, 0x72, 0x22, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x7d, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73,
 | 
			
		||||
  0x74, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
 | 
			
		||||
  0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x28, 0x74, 0x72,
 | 
			
		||||
  0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x29, 0x20, 0x3d, 0x3e,
 | 
			
		||||
  0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x65, 0x73,
 | 
			
		||||
  0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d,
 | 
			
		||||
  0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e,
 | 
			
		||||
  0x2e, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61,
 | 
			
		||||
  0x6c, 0x75, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
 | 
			
		||||
  0x20, 0x63, 0x68, 0x61, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x28,
 | 
			
		||||
  0x28, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
 | 
			
		||||
  0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e,
 | 
			
		||||
  0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2e, 0x6c, 0x65, 0x6e, 0x67, 0x74,
 | 
			
		||||
  0x68, 0x20, 0x3e, 0x20, 0x30, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x28, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x64,
 | 
			
		||||
  0x69, 0x63, 0x74, 0x3a, 0x20, 0x34, 0x30, 0x30, 0x2c, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74,
 | 
			
		||||
  0x75, 0x72, 0x65, 0x3a, 0x20, 0x30, 0x2e, 0x37, 0x2c, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x6c,
 | 
			
		||||
  0x61, 0x73, 0x74, 0x5f, 0x6e, 0x3a, 0x20, 0x32, 0x35, 0x36, 0x2c, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74,
 | 
			
		||||
  0x5f, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x3a, 0x20, 0x31, 0x2e,
 | 
			
		||||
  0x31, 0x38, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f,
 | 
			
		||||
  0x70, 0x5f, 0x6b, 0x3a, 0x20, 0x34, 0x30, 0x2c, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x74, 0x6f, 0x70, 0x5f, 0x70, 0x3a, 0x20, 0x30, 0x2e,
 | 
			
		||||
  0x35, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x0a, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e,
 | 
			
		||||
  0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x73, 0x69,
 | 
			
		||||
  0x67, 0x6e, 0x61, 0x6c, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x65, 0x6e,
 | 
			
		||||
  0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x63, 0x6f,
 | 
			
		||||
  0x6d, 0x70, 0x75, 0x74, 0x65, 0x64, 0x28, 0x28, 0x29, 0x20, 0x3d, 0x3e,
 | 
			
		||||
  0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
 | 
			
		||||
  0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x75, 0x6c,
 | 
			
		||||
  0x6c, 0x20, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20,
 | 
			
		||||
  0x73, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c,
 | 
			
		||||
  0x61, 0x74, 0x65, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x74, 0x65,
 | 
			
		||||
  0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x28, 0x73, 0x74,
 | 
			
		||||
  0x72, 0x2c, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x53, 0x65, 0x74, 0x74,
 | 
			
		||||
  0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x65, 0x74, 0x20, 0x73, 0x65, 0x74,
 | 
			
		||||
  0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x73, 0x73,
 | 
			
		||||
  0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x65, 0x78, 0x74,
 | 
			
		||||
  0x72, 0x61, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x20,
 | 
			
		||||
  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x65,
 | 
			
		||||
  0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x2e,
 | 
			
		||||
  0x2e, 0x2e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20,
 | 
			
		||||
  0x2e, 0x2e, 0x2e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x53, 0x65, 0x74, 0x74,
 | 
			
		||||
  0x69, 0x6e, 0x67, 0x73, 0x20, 0x7d, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
 | 
			
		||||
  0x74, 0x75, 0x72, 0x6e, 0x20, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28,
 | 
			
		||||
  0x73, 0x74, 0x72, 0x29, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65,
 | 
			
		||||
  0x41, 0x6c, 0x6c, 0x28, 0x2f, 0x5c, 0x7b, 0x5c, 0x7b, 0x28, 0x2e, 0x2a,
 | 
			
		||||
  0x3f, 0x29, 0x5c, 0x7d, 0x5c, 0x7d, 0x2f, 0x67, 0x2c, 0x20, 0x28, 0x5f,
 | 
			
		||||
  0x2c, 0x20, 0x6b, 0x65, 0x79, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x74, 0x65,
 | 
			
		||||
  0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69,
 | 
			
		||||
  0x6e, 0x67, 0x73, 0x5b, 0x6b, 0x65, 0x79, 0x5d, 0x29, 0x29, 0x3b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2f,
 | 
			
		||||
  0x2f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
 | 
			
		||||
  0x67, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63,
 | 
			
		||||
  0x68, 0x61, 0x74, 0x20, 0x3d, 0x20, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x20,
 | 
			
		||||
  0x28, 0x6d, 0x73, 0x67, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x63, 0x6f, 0x6e,
 | 
			
		||||
  0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x61, 0x6c, 0x75,
 | 
			
		||||
  0x65, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x67,
 | 
			
		||||
  0x28, 0x27, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x72, 0x75,
 | 
			
		||||
  0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x2e, 0x2e, 0x27, 0x29, 0x3b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75,
 | 
			
		||||
  0x72, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
 | 
			
		||||
  0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d,
 | 
			
		||||
  0x20, 0x6e, 0x65, 0x77, 0x20, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x43, 0x6f,
 | 
			
		||||
  0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x28, 0x29, 0x3b, 0x0a,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73,
 | 
			
		||||
  0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28,
 | 
			
		||||
  0x5b, 0x2e, 0x2e, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e,
 | 
			
		||||
  0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63,
 | 
			
		||||
  0x72, 0x69, 0x70, 0x74, 0x2c, 0x20, 0x5b, 0x22, 0x7b, 0x7b, 0x75, 0x73,
 | 
			
		||||
  0x65, 0x72, 0x7d, 0x7d, 0x22, 0x2c, 0x20, 0x6d, 0x73, 0x67, 0x5d, 0x5d,
 | 
			
		||||
  0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e,
 | 
			
		||||
  0x73, 0x74, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x3d,
 | 
			
		||||
  0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x73, 0x65,
 | 
			
		||||
  0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e,
 | 
			
		||||
  0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x20, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, 0x73, 0x73,
 | 
			
		||||
  0x61, 0x67, 0x65, 0x3a, 0x20, 0x6d, 0x73, 0x67, 0x2c, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72,
 | 
			
		||||
  0x79, 0x3a, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76,
 | 
			
		||||
  0x61, 0x6c, 0x75, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72,
 | 
			
		||||
  0x69, 0x70, 0x74, 0x2e, 0x66, 0x6c, 0x61, 0x74, 0x4d, 0x61, 0x70, 0x28,
 | 
			
		||||
  0x28, 0x5b, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x6d, 0x65, 0x73, 0x73,
 | 
			
		||||
  0x61, 0x67, 0x65, 0x5d, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x74, 0x65, 0x6d,
 | 
			
		||||
  0x70, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
 | 
			
		||||
  0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x68, 0x69, 0x73, 0x74,
 | 
			
		||||
  0x6f, 0x72, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x2c,
 | 
			
		||||
  0x20, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x6d, 0x65, 0x73, 0x73,
 | 
			
		||||
  0x61, 0x67, 0x65, 0x7d, 0x29, 0x29, 0x2e, 0x6a, 0x6f, 0x69, 0x6e, 0x28,
 | 
			
		||||
  0x22, 0x5c, 0x6e, 0x22, 0x29, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x7d, 0x29, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x6c, 0x65, 0x74, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4d,
 | 
			
		||||
  0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x27, 0x27, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
 | 
			
		||||
  0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x3d, 0x20, 0x73,
 | 
			
		||||
  0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65,
 | 
			
		||||
  0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x0a,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
 | 
			
		||||
  0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x2e, 0x2e, 0x2e, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x76,
 | 
			
		||||
  0x61, 0x6c, 0x75, 0x65, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x3a, 0x20, 0x70, 0x61,
 | 
			
		||||
  0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x20, 0x5b, 0x22, 0x3c,
 | 
			
		||||
  0x2f, 0x73, 0x3e, 0x22, 0x2c, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61,
 | 
			
		||||
  0x74, 0x65, 0x28, 0x22, 0x7b, 0x7b, 0x63, 0x68, 0x61, 0x72, 0x7d, 0x7d,
 | 
			
		||||
  0x3a, 0x22, 0x29, 0x2c, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74,
 | 
			
		||||
  0x65, 0x28, 0x22, 0x7b, 0x7b, 0x75, 0x73, 0x65, 0x72, 0x7d, 0x7d, 0x3a,
 | 
			
		||||
  0x22, 0x29, 0x5d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
 | 
			
		||||
  0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x61, 0x77, 0x61, 0x69,
 | 
			
		||||
  0x74, 0x20, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x43, 0x6f, 0x6d, 0x70, 0x6c,
 | 
			
		||||
  0x65, 0x74, 0x65, 0x28, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x50, 0x61, 0x72,
 | 
			
		||||
  0x61, 0x6d, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
 | 
			
		||||
  0x6c, 0x65, 0x72, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x28,
 | 
			
		||||
  0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x29, 0x20, 0x3d, 0x3e, 0x20,
 | 
			
		||||
  0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
 | 
			
		||||
  0x6e, 0x73, 0x74, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x3d, 0x20, 0x6d,
 | 
			
		||||
  0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x75, 0x72,
 | 
			
		||||
  0x72, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20,
 | 
			
		||||
  0x2b, 0x3d, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
 | 
			
		||||
  0x65, 0x6e, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x2f, 0x2f, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x6c,
 | 
			
		||||
  0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x68, 0x69, 0x74, 0x65,
 | 
			
		||||
  0x73, 0x70, 0x61, 0x63, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73,
 | 
			
		||||
  0x73, 0x61, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65,
 | 
			
		||||
  0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x72, 0x65,
 | 
			
		||||
  0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x2f, 0x5e, 0x5c, 0x73, 0x2b, 0x2f,
 | 
			
		||||
  0x2c, 0x20, 0x22, 0x22, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70,
 | 
			
		||||
  0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x5b, 0x2e, 0x2e, 0x2e,
 | 
			
		||||
  0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x2c, 0x20, 0x5b, 0x22, 0x7b,
 | 
			
		||||
  0x7b, 0x63, 0x68, 0x61, 0x72, 0x7d, 0x7d, 0x22, 0x2c, 0x20, 0x63, 0x75,
 | 
			
		||||
  0x72, 0x72, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
 | 
			
		||||
  0x5d, 0x5d, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x69, 0x66, 0x20, 0x28, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x73, 0x74,
 | 
			
		||||
  0x6f, 0x70, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e,
 | 
			
		||||
  0x6c, 0x6f, 0x67, 0x28, 0x22, 0x2d, 0x2d, 0x3e, 0x22, 0x2c, 0x20, 0x64,
 | 
			
		||||
  0x61, 0x74, 0x61, 0x2c, 0x20, 0x27, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f,
 | 
			
		||||
  0x6e, 0x73, 0x65, 0x20, 0x77, 0x61, 0x73, 0x3a, 0x27, 0x2c, 0x20, 0x63,
 | 
			
		||||
  0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
 | 
			
		||||
  0x65, 0x2c, 0x20, 0x27, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69,
 | 
			
		||||
  0x70, 0x74, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3a, 0x27, 0x2c, 0x20,
 | 
			
		||||
  0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75,
 | 
			
		||||
  0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
 | 
			
		||||
  0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x29, 0x0a, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
 | 
			
		||||
  0x6c, 0x65, 0x72, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20,
 | 
			
		||||
  0x6e, 0x75, 0x6c, 0x6c, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
 | 
			
		||||
  0x6e, 0x20, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x6e, 0x70,
 | 
			
		||||
  0x75, 0x74, 0x28, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
 | 
			
		||||
  0x67, 0x65, 0x20, 0x3d, 0x20, 0x75, 0x73, 0x65, 0x53, 0x69, 0x67, 0x6e,
 | 
			
		||||
  0x61, 0x6c, 0x28, 0x22, 0x22, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x73, 0x74, 0x6f, 0x70,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x28, 0x65, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x2e, 0x70, 0x72,
 | 
			
		||||
  0x65, 0x76, 0x65, 0x6e, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
 | 
			
		||||
  0x28, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x69, 0x66, 0x20, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
 | 
			
		||||
  0x65, 0x72, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x7b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
 | 
			
		||||
  0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x61, 0x6c,
 | 
			
		||||
  0x75, 0x65, 0x2e, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x28, 0x29, 0x3b, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
 | 
			
		||||
  0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x76, 0x61, 0x6c,
 | 
			
		||||
  0x75, 0x65, 0x20, 0x3d, 0x20, 0x6e, 0x75, 0x6c, 0x6c, 0x3b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20,
 | 
			
		||||
  0x3d, 0x20, 0x28, 0x65, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x6f, 0x70, 0x28,
 | 
			
		||||
  0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70,
 | 
			
		||||
  0x64, 0x61, 0x74, 0x65, 0x28, 0x5b, 0x5d, 0x29, 0x3b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x69,
 | 
			
		||||
  0x74, 0x20, 0x3d, 0x20, 0x28, 0x65, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x74, 0x6f,
 | 
			
		||||
  0x70, 0x28, 0x65, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x63, 0x68, 0x61, 0x74, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61,
 | 
			
		||||
  0x67, 0x65, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x3b, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
 | 
			
		||||
  0x67, 0x65, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20, 0x22,
 | 
			
		||||
  0x22, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20,
 | 
			
		||||
  0x65, 0x6e, 0x74, 0x65, 0x72, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x73,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x29, 0x20, 0x3d,
 | 
			
		||||
  0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x69, 0x66, 0x20, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x77, 0x68,
 | 
			
		||||
  0x69, 0x63, 0x68, 0x20, 0x3d, 0x3d, 0x3d, 0x20, 0x31, 0x33, 0x20, 0x26,
 | 
			
		||||
  0x26, 0x20, 0x21, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x68, 0x69,
 | 
			
		||||
  0x66, 0x74, 0x4b, 0x65, 0x79, 0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x69,
 | 
			
		||||
  0x74, 0x28, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x29, 0x3b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72,
 | 
			
		||||
  0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x60, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x66, 0x6f, 0x72,
 | 
			
		||||
  0x6d, 0x20, 0x6f, 0x6e, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x3d, 0x24,
 | 
			
		||||
  0x7b, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x7d, 0x3e, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76,
 | 
			
		||||
  0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x74, 0x79,
 | 
			
		||||
  0x70, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x72, 0x6f,
 | 
			
		||||
  0x77, 0x73, 0x3d, 0x32, 0x20, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x70, 0x72,
 | 
			
		||||
  0x65, 0x73, 0x73, 0x3d, 0x24, 0x7b, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x53,
 | 
			
		||||
  0x75, 0x62, 0x6d, 0x69, 0x74, 0x73, 0x7d, 0x20, 0x76, 0x61, 0x6c, 0x75,
 | 
			
		||||
  0x65, 0x3d, 0x22, 0x24, 0x7b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
 | 
			
		||||
  0x7d, 0x22, 0x20, 0x6f, 0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3d, 0x24,
 | 
			
		||||
  0x7b, 0x28, 0x65, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x6d, 0x65, 0x73, 0x73,
 | 
			
		||||
  0x61, 0x67, 0x65, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20,
 | 
			
		||||
  0x65, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x76, 0x61, 0x6c,
 | 
			
		||||
  0x75, 0x65, 0x7d, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c,
 | 
			
		||||
  0x64, 0x65, 0x72, 0x3d, 0x22, 0x53, 0x61, 0x79, 0x20, 0x73, 0x6f, 0x6d,
 | 
			
		||||
  0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x2e, 0x2e, 0x2e, 0x22, 0x2f, 0x3e,
 | 
			
		||||
  0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x63, 0x6c,
 | 
			
		||||
  0x61, 0x73, 0x73, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d,
 | 
			
		||||
  0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x22, 0x20, 0x64, 0x69, 0x73,
 | 
			
		||||
  0x61, 0x62, 0x6c, 0x65, 0x64, 0x3d, 0x24, 0x7b, 0x21, 0x67, 0x65, 0x6e,
 | 
			
		||||
  0x65, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x61, 0x6c, 0x75,
 | 
			
		||||
  0x65, 0x7d, 0x20, 0x3e, 0x53, 0x65, 0x6e, 0x64, 0x3c, 0x2f, 0x62, 0x75,
 | 
			
		||||
  0x74, 0x74, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20,
 | 
			
		||||
  0x6f, 0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x24, 0x7b, 0x73, 0x74,
 | 
			
		||||
  0x6f, 0x70, 0x7d, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64,
 | 
			
		||||
  0x3d, 0x24, 0x7b, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6e,
 | 
			
		||||
  0x67, 0x7d, 0x3e, 0x53, 0x74, 0x6f, 0x70, 0x3c, 0x2f, 0x62, 0x75, 0x74,
 | 
			
		||||
  0x74, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x3c, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x20, 0x6f,
 | 
			
		||||
  0x6e, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x3d, 0x24, 0x7b, 0x72, 0x65, 0x73,
 | 
			
		||||
  0x65, 0x74, 0x7d, 0x3e, 0x52, 0x65, 0x73, 0x65, 0x74, 0x3c, 0x2f, 0x62,
 | 
			
		||||
  0x75, 0x74, 0x74, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x66, 0x6f,
 | 
			
		||||
  0x72, 0x6d, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63,
 | 
			
		||||
  0x6f, 0x6e, 0x73, 0x74, 0x20, 0x43, 0x68, 0x61, 0x74, 0x4c, 0x6f, 0x67,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x28, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x29, 0x20, 0x3d,
 | 
			
		||||
  0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f,
 | 
			
		||||
  0x6e, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76,
 | 
			
		||||
  0x61, 0x6c, 0x75, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x63, 0x72,
 | 
			
		||||
  0x69, 0x70, 0x74, 0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63,
 | 
			
		||||
  0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
 | 
			
		||||
  0x65, 0x72, 0x20, 0x3d, 0x20, 0x75, 0x73, 0x65, 0x52, 0x65, 0x66, 0x28,
 | 
			
		||||
  0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x75, 0x73, 0x65, 0x45, 0x66, 0x66, 0x65, 0x63, 0x74, 0x28, 0x28,
 | 
			
		||||
  0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c,
 | 
			
		||||
  0x20, 0x74, 0x6f, 0x20, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x20, 0x28,
 | 
			
		||||
  0x69, 0x66, 0x20, 0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x29, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28, 0x63,
 | 
			
		||||
  0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x63, 0x75, 0x72,
 | 
			
		||||
  0x72, 0x65, 0x6e, 0x74, 0x20, 0x26, 0x26, 0x20, 0x63, 0x6f, 0x6e, 0x74,
 | 
			
		||||
  0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
 | 
			
		||||
  0x74, 0x2e, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x65, 0x69, 0x67,
 | 
			
		||||
  0x68, 0x74, 0x20, 0x3c, 0x3d, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
 | 
			
		||||
  0x6e, 0x65, 0x72, 0x2e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2e,
 | 
			
		||||
  0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x54, 0x6f, 0x70, 0x20, 0x2b, 0x20,
 | 
			
		||||
  0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x63, 0x75,
 | 
			
		||||
  0x72, 0x72, 0x65, 0x6e, 0x74, 0x2e, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74,
 | 
			
		||||
  0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x2b, 0x20, 0x33, 0x30, 0x30,
 | 
			
		||||
  0x29, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e,
 | 
			
		||||
  0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x2e, 0x73, 0x63, 0x72, 0x6f,
 | 
			
		||||
  0x6c, 0x6c, 0x54, 0x6f, 0x28, 0x30, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74,
 | 
			
		||||
  0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
 | 
			
		||||
  0x74, 0x2e, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x48, 0x65, 0x69, 0x67,
 | 
			
		||||
  0x68, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x2c, 0x20, 0x5b,
 | 
			
		||||
  0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x5d, 0x29, 0x0a, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20,
 | 
			
		||||
  0x63, 0x68, 0x61, 0x74, 0x4c, 0x69, 0x6e, 0x65, 0x20, 0x3d, 0x20, 0x28,
 | 
			
		||||
  0x5b, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x20, 0x6d, 0x73, 0x67, 0x5d, 0x29,
 | 
			
		||||
  0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x68, 0x74, 0x6d,
 | 
			
		||||
  0x6c, 0x60, 0x3c, 0x70, 0x20, 0x6b, 0x65, 0x79, 0x3d, 0x24, 0x7b, 0x6d,
 | 
			
		||||
  0x73, 0x67, 0x7d, 0x3e, 0x3c, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x3e,
 | 
			
		||||
  0x24, 0x7b, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x75,
 | 
			
		||||
  0x73, 0x65, 0x72, 0x29, 0x7d, 0x3a, 0x3c, 0x2f, 0x73, 0x74, 0x72, 0x6f,
 | 
			
		||||
  0x6e, 0x67, 0x3e, 0x20, 0x3c, 0x24, 0x7b, 0x4d, 0x61, 0x72, 0x6b, 0x64,
 | 
			
		||||
  0x6f, 0x77, 0x6e, 0x7d, 0x20, 0x74, 0x65, 0x78, 0x74, 0x3d, 0x24, 0x7b,
 | 
			
		||||
  0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x28, 0x6d, 0x73, 0x67,
 | 
			
		||||
  0x29, 0x7d, 0x20, 0x2f, 0x3e, 0x3c, 0x2f, 0x70, 0x3e, 0x60, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x68, 0x74,
 | 
			
		||||
  0x6d, 0x6c, 0x60, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x64, 0x3d,
 | 
			
		||||
  0x22, 0x63, 0x68, 0x61, 0x74, 0x22, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x24,
 | 
			
		||||
  0x7b, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x7d, 0x3e,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x24,
 | 
			
		||||
  0x7b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x66, 0x6c,
 | 
			
		||||
  0x61, 0x74, 0x4d, 0x61, 0x70, 0x28, 0x63, 0x68, 0x61, 0x74, 0x4c, 0x69,
 | 
			
		||||
  0x6e, 0x65, 0x29, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x3c, 0x2f, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x60,
 | 
			
		||||
  0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x6e, 0x66,
 | 
			
		||||
  0x69, 0x67, 0x46, 0x6f, 0x72, 0x6d, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x72,
 | 
			
		||||
  0x6f, 0x70, 0x73, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x70,
 | 
			
		||||
  0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
 | 
			
		||||
  0x3d, 0x20, 0x28, 0x65, 0x6c, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x73, 0x65,
 | 
			
		||||
  0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20,
 | 
			
		||||
  0x3d, 0x20, 0x7b, 0x20, 0x2e, 0x2e, 0x2e, 0x73, 0x65, 0x73, 0x73, 0x69,
 | 
			
		||||
  0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x5b, 0x65,
 | 
			
		||||
  0x6c, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x6e, 0x61, 0x6d,
 | 
			
		||||
  0x65, 0x5d, 0x3a, 0x20, 0x65, 0x6c, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65,
 | 
			
		||||
  0x74, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x7d, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x70,
 | 
			
		||||
  0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x3d,
 | 
			
		||||
  0x20, 0x28, 0x65, 0x6c, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x70, 0x61, 0x72,
 | 
			
		||||
  0x61, 0x6d, 0x73, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x3d, 0x20,
 | 
			
		||||
  0x7b, 0x20, 0x2e, 0x2e, 0x2e, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e,
 | 
			
		||||
  0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x5b, 0x65, 0x6c, 0x2e, 0x74,
 | 
			
		||||
  0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x3a,
 | 
			
		||||
  0x20, 0x65, 0x6c, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x76,
 | 
			
		||||
  0x61, 0x6c, 0x75, 0x65, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74,
 | 
			
		||||
  0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x46, 0x6c, 0x6f, 0x61, 0x74,
 | 
			
		||||
  0x20, 0x3d, 0x20, 0x28, 0x65, 0x6c, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x70,
 | 
			
		||||
  0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20,
 | 
			
		||||
  0x3d, 0x20, 0x7b, 0x20, 0x2e, 0x2e, 0x2e, 0x70, 0x61, 0x72, 0x61, 0x6d,
 | 
			
		||||
  0x73, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2c, 0x20, 0x5b, 0x65, 0x6c,
 | 
			
		||||
  0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x6e, 0x61, 0x6d, 0x65,
 | 
			
		||||
  0x5d, 0x3a, 0x20, 0x70, 0x61, 0x72, 0x73, 0x65, 0x46, 0x6c, 0x6f, 0x61,
 | 
			
		||||
  0x74, 0x28, 0x65, 0x6c, 0x2e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e,
 | 
			
		||||
  0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x68,
 | 
			
		||||
  0x74, 0x6d, 0x6c, 0x60, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x66, 0x69, 0x65, 0x6c, 0x64,
 | 
			
		||||
  0x73, 0x65, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x3c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d,
 | 
			
		||||
  0x22, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x22, 0x3e, 0x50, 0x72, 0x6f,
 | 
			
		||||
  0x6d, 0x70, 0x74, 0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3e, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x3c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20,
 | 
			
		||||
  0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20,
 | 
			
		||||
  0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74,
 | 
			
		||||
  0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x24, 0x7b, 0x73,
 | 
			
		||||
  0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65,
 | 
			
		||||
  0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x7d, 0x22, 0x20, 0x72, 0x6f,
 | 
			
		||||
  0x77, 0x73, 0x3d, 0x34, 0x20, 0x6f, 0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74,
 | 
			
		||||
  0x3d, 0x24, 0x7b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73,
 | 
			
		||||
  0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69,
 | 
			
		||||
  0x76, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x22,
 | 
			
		||||
  0x75, 0x73, 0x65, 0x72, 0x22, 0x3e, 0x55, 0x73, 0x65, 0x72, 0x20, 0x6e,
 | 
			
		||||
  0x61, 0x6d, 0x65, 0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3e, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70,
 | 
			
		||||
  0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x6e, 0x61, 0x6d,
 | 
			
		||||
  0x65, 0x3d, 0x22, 0x75, 0x73, 0x65, 0x72, 0x22, 0x20, 0x76, 0x61, 0x6c,
 | 
			
		||||
  0x75, 0x65, 0x3d, 0x22, 0x24, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
 | 
			
		||||
  0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x75, 0x73, 0x65, 0x72,
 | 
			
		||||
  0x7d, 0x22, 0x20, 0x6f, 0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3d, 0x24,
 | 
			
		||||
  0x7b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69,
 | 
			
		||||
  0x6f, 0x6e, 0x7d, 0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69, 0x76,
 | 
			
		||||
  0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x22, 0x62,
 | 
			
		||||
  0x6f, 0x74, 0x22, 0x3e, 0x42, 0x6f, 0x74, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 | 
			
		||||
  0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22,
 | 
			
		||||
  0x74, 0x65, 0x78, 0x74, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22,
 | 
			
		||||
  0x63, 0x68, 0x61, 0x72, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d,
 | 
			
		||||
  0x22, 0x24, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76,
 | 
			
		||||
  0x61, 0x6c, 0x75, 0x65, 0x2e, 0x63, 0x68, 0x61, 0x72, 0x7d, 0x22, 0x20,
 | 
			
		||||
  0x6f, 0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3d, 0x24, 0x7b, 0x75, 0x70,
 | 
			
		||||
  0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x7d,
 | 
			
		||||
  0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x61, 0x62,
 | 
			
		||||
  0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x22, 0x74, 0x65, 0x6d, 0x70,
 | 
			
		||||
  0x6c, 0x61, 0x74, 0x65, 0x22, 0x3e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74,
 | 
			
		||||
  0x20, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x6c,
 | 
			
		||||
  0x61, 0x62, 0x65, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x65, 0x78,
 | 
			
		||||
  0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x65,
 | 
			
		||||
  0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 | 
			
		||||
  0x3d, 0x22, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x20,
 | 
			
		||||
  0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x24, 0x7b, 0x73, 0x65, 0x73,
 | 
			
		||||
  0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x74,
 | 
			
		||||
  0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x7d, 0x22, 0x20, 0x72, 0x6f,
 | 
			
		||||
  0x77, 0x73, 0x3d, 0x34, 0x20, 0x6f, 0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74,
 | 
			
		||||
  0x3d, 0x24, 0x7b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73,
 | 
			
		||||
  0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69,
 | 
			
		||||
  0x76, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x22,
 | 
			
		||||
  0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x3e, 0x43, 0x68,
 | 
			
		||||
  0x61, 0x74, 0x20, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x74,
 | 
			
		||||
  0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x6c, 0x61, 0x62,
 | 
			
		||||
  0x65, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x65, 0x78, 0x74, 0x61,
 | 
			
		||||
  0x72, 0x65, 0x61, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x65, 0x6d, 0x70,
 | 
			
		||||
  0x6c, 0x61, 0x74, 0x65, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22,
 | 
			
		||||
  0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x65, 0x6d, 0x70, 0x6c,
 | 
			
		||||
  0x61, 0x74, 0x65, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22,
 | 
			
		||||
  0x24, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x61,
 | 
			
		||||
  0x6c, 0x75, 0x65, 0x2e, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x54,
 | 
			
		||||
  0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x7d, 0x22, 0x20, 0x72, 0x6f,
 | 
			
		||||
  0x77, 0x73, 0x3d, 0x31, 0x20, 0x6f, 0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74,
 | 
			
		||||
  0x3d, 0x24, 0x7b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73,
 | 
			
		||||
  0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69,
 | 
			
		||||
  0x76, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x22,
 | 
			
		||||
  0x74, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22,
 | 
			
		||||
  0x3e, 0x54, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65,
 | 
			
		||||
  0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22,
 | 
			
		||||
  0x72, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74,
 | 
			
		||||
  0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x20,
 | 
			
		||||
  0x6d, 0x69, 0x6e, 0x3d, 0x22, 0x30, 0x2e, 0x30, 0x22, 0x20, 0x6d, 0x61,
 | 
			
		||||
  0x78, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x73, 0x74, 0x65, 0x70,
 | 
			
		||||
  0x3d, 0x22, 0x30, 0x2e, 0x30, 0x31, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 | 
			
		||||
  0x3d, 0x22, 0x74, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72,
 | 
			
		||||
  0x65, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x24, 0x7b,
 | 
			
		||||
  0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65,
 | 
			
		||||
  0x2e, 0x74, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65,
 | 
			
		||||
  0x7d, 0x22, 0x20, 0x6f, 0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3d, 0x24,
 | 
			
		||||
  0x7b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d,
 | 
			
		||||
  0x73, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x7d, 0x20, 0x2f, 0x3e, 0x0a, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x3c, 0x73, 0x70, 0x61, 0x6e, 0x3e, 0x24, 0x7b, 0x70, 0x61, 0x72,
 | 
			
		||||
  0x61, 0x6d, 0x73, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x74, 0x65,
 | 
			
		||||
  0x6d, 0x70, 0x65, 0x72, 0x61, 0x74, 0x75, 0x72, 0x65, 0x7d, 0x3c, 0x2f,
 | 
			
		||||
  0x73, 0x70, 0x61, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
 | 
			
		||||
  0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x3c, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6c,
 | 
			
		||||
  0x61, 0x62, 0x65, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x3d, 0x22, 0x6e, 0x50,
 | 
			
		||||
  0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x22, 0x3e, 0x50, 0x72, 0x65, 0x64,
 | 
			
		||||
  0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3c, 0x2f, 0x6c, 0x61, 0x62,
 | 
			
		||||
  0x65, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74,
 | 
			
		||||
  0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x72, 0x61, 0x6e, 0x67, 0x65,
 | 
			
		||||
  0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6e, 0x50, 0x72, 0x65, 0x64, 0x69,
 | 
			
		||||
  0x63, 0x74, 0x22, 0x20, 0x6d, 0x69, 0x6e, 0x3d, 0x22, 0x31, 0x22, 0x20,
 | 
			
		||||
  0x6d, 0x61, 0x78, 0x3d, 0x22, 0x32, 0x30, 0x34, 0x38, 0x22, 0x20, 0x73,
 | 
			
		||||
  0x74, 0x65, 0x70, 0x3d, 0x22, 0x31, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65,
 | 
			
		||||
  0x3d, 0x22, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x22,
 | 
			
		||||
  0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x24, 0x7b, 0x70, 0x61,
 | 
			
		||||
  0x72, 0x61, 0x6d, 0x73, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x6e,
 | 
			
		||||
  0x5f, 0x70, 0x72, 0x65, 0x64, 0x69, 0x63, 0x74, 0x7d, 0x22, 0x20, 0x6f,
 | 
			
		||||
  0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3d, 0x24, 0x7b, 0x75, 0x70, 0x64,
 | 
			
		||||
  0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x46, 0x6c, 0x6f,
 | 
			
		||||
  0x61, 0x74, 0x7d, 0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x73, 0x70,
 | 
			
		||||
  0x61, 0x6e, 0x3e, 0x24, 0x7b, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e,
 | 
			
		||||
  0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x64,
 | 
			
		||||
  0x69, 0x63, 0x74, 0x7d, 0x3c, 0x2f, 0x73, 0x70, 0x61, 0x6e, 0x3e, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64, 0x69, 0x76,
 | 
			
		||||
  0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x20, 0x66,
 | 
			
		||||
  0x6f, 0x72, 0x3d, 0x22, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x70,
 | 
			
		||||
  0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x22, 0x3e, 0x50, 0x65, 0x6e, 0x61,
 | 
			
		||||
  0x6c, 0x69, 0x7a, 0x65, 0x20, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x20,
 | 
			
		||||
  0x73, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x3c, 0x2f, 0x6c, 0x61,
 | 
			
		||||
  0x62, 0x65, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x69, 0x6e, 0x70, 0x75,
 | 
			
		||||
  0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x72, 0x61, 0x6e, 0x67,
 | 
			
		||||
  0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x72, 0x65, 0x70, 0x65, 0x61,
 | 
			
		||||
  0x74, 0x5f, 0x70, 0x65, 0x6e, 0x61, 0x6c, 0x74, 0x79, 0x22, 0x20, 0x6d,
 | 
			
		||||
  0x69, 0x6e, 0x3d, 0x22, 0x30, 0x2e, 0x30, 0x22, 0x20, 0x6d, 0x61, 0x78,
 | 
			
		||||
  0x3d, 0x22, 0x32, 0x2e, 0x30, 0x22, 0x20, 0x73, 0x74, 0x65, 0x70, 0x3d,
 | 
			
		||||
  0x22, 0x30, 0x2e, 0x30, 0x31, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d,
 | 
			
		||||
  0x22, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x70, 0x65, 0x6e, 0x61,
 | 
			
		||||
  0x6c, 0x74, 0x79, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22,
 | 
			
		||||
  0x24, 0x7b, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x76, 0x61, 0x6c,
 | 
			
		||||
  0x75, 0x65, 0x2e, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x70, 0x65,
 | 
			
		||||
  0x6e, 0x61, 0x6c, 0x74, 0x79, 0x7d, 0x22, 0x20, 0x6f, 0x6e, 0x69, 0x6e,
 | 
			
		||||
  0x70, 0x75, 0x74, 0x3d, 0x24, 0x7b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
 | 
			
		||||
  0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x7d,
 | 
			
		||||
  0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x73, 0x70, 0x61, 0x6e, 0x3e,
 | 
			
		||||
  0x24, 0x7b, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x76, 0x61, 0x6c,
 | 
			
		||||
  0x75, 0x65, 0x2e, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x70, 0x65,
 | 
			
		||||
  0x6e, 0x61, 0x6c, 0x74, 0x79, 0x7d, 0x3c, 0x2f, 0x73, 0x70, 0x61, 0x6e,
 | 
			
		||||
  0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0x0a, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x64,
 | 
			
		||||
  0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x61, 0x62, 0x65, 0x6c,
 | 
			
		||||
  0x20, 0x66, 0x6f, 0x72, 0x3d, 0x22, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74,
 | 
			
		||||
  0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x22, 0x3e, 0x43, 0x6f, 0x6e,
 | 
			
		||||
  0x73, 0x69, 0x64, 0x65, 0x72, 0x20, 0x4e, 0x20, 0x74, 0x6f, 0x6b, 0x65,
 | 
			
		||||
  0x6e, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x65, 0x6e, 0x61, 0x6c,
 | 
			
		||||
  0x69, 0x7a, 0x65, 0x3c, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x3e, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70,
 | 
			
		||||
  0x65, 0x3d, 0x22, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x20, 0x69, 0x64,
 | 
			
		||||
  0x3d, 0x22, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x5f, 0x6c, 0x61, 0x73,
 | 
			
		||||
  0x74, 0x5f, 0x6e, 0x22, 0x20, 0x6d, 0x69, 0x6e, 0x3d, 0x22, 0x30, 0x2e,
 | 
			
		||||
  0x30, 0x22, 0x20, 0x6d, 0x61, 0x78, 0x3d, 0x22, 0x32, 0x30, 0x34, 0x38,
 | 
			
		||||
  0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x65, 0x70, 0x65,
 | 
			
		||||
  0x61, 0x74, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x22, 0x20, 0x76,
 | 
			
		||||
  0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x24, 0x7b, 0x70, 0x61, 0x72, 0x61,
 | 
			
		||||
  0x6d, 0x73, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x72, 0x65, 0x70,
 | 
			
		||||
  0x65, 0x61, 0x74, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x7d, 0x22,
 | 
			
		||||
  0x20, 0x6f, 0x6e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x3d, 0x24, 0x7b, 0x75,
 | 
			
		||||
  0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x46,
 | 
			
		||||
  0x6c, 0x6f, 0x61, 0x74, 0x7d, 0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x73, 0x70, 0x61, 0x6e, 0x3e, 0x24, 0x7b, 0x70, 0x61, 0x72, 0x61, 0x6d,
 | 
			
		||||
  0x73, 0x2e, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2e, 0x72, 0x65, 0x70, 0x65,
 | 
			
		||||
  0x61, 0x74, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x7d, 0x3c, 0x2f,
 | 
			
		||||
  0x73, 0x70, 0x61, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e,
 | 
			
		||||
  0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x65, 0x74, 0x3e, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x66, 0x6f,
 | 
			
		||||
  0x72, 0x6d, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20,
 | 
			
		||||
  0x4d, 0x61, 0x72, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x20, 0x3d, 0x20, 0x28,
 | 
			
		||||
  0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x20, 0x3d, 0x3e, 0x20, 0x7b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x6d, 0x64, 0x20,
 | 
			
		||||
  0x3d, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x74, 0x65, 0x78,
 | 
			
		||||
  0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x61,
 | 
			
		||||
  0x63, 0x65, 0x28, 0x2f, 0x5e, 0x23, 0x7b, 0x31, 0x2c, 0x36, 0x7d, 0x20,
 | 
			
		||||
  0x28, 0x2e, 0x2a, 0x29, 0x24, 0x2f, 0x67, 0x69, 0x6d, 0x2c, 0x20, 0x27,
 | 
			
		||||
  0x3c, 0x68, 0x33, 0x3e, 0x24, 0x31, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0x27,
 | 
			
		||||
  0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x61,
 | 
			
		||||
  0x63, 0x65, 0x28, 0x2f, 0x5c, 0x2a, 0x5c, 0x2a, 0x28, 0x2e, 0x2a, 0x3f,
 | 
			
		||||
  0x29, 0x5c, 0x2a, 0x5c, 0x2a, 0x2f, 0x67, 0x2c, 0x20, 0x27, 0x3c, 0x73,
 | 
			
		||||
  0x74, 0x72, 0x6f, 0x6e, 0x67, 0x3e, 0x24, 0x31, 0x3c, 0x2f, 0x73, 0x74,
 | 
			
		||||
  0x72, 0x6f, 0x6e, 0x67, 0x3e, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x2e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x2f, 0x5f, 0x5f,
 | 
			
		||||
  0x28, 0x2e, 0x2a, 0x3f, 0x29, 0x5f, 0x5f, 0x2f, 0x67, 0x2c, 0x20, 0x27,
 | 
			
		||||
  0x3c, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x3e, 0x24, 0x31, 0x3c, 0x2f,
 | 
			
		||||
  0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67, 0x3e, 0x27, 0x29, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x2f,
 | 
			
		||||
  0x5c, 0x2a, 0x28, 0x2e, 0x2a, 0x3f, 0x29, 0x5c, 0x2a, 0x2f, 0x67, 0x2c,
 | 
			
		||||
  0x20, 0x27, 0x3c, 0x65, 0x6d, 0x3e, 0x24, 0x31, 0x3c, 0x2f, 0x65, 0x6d,
 | 
			
		||||
  0x3e, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x72, 0x65, 0x70,
 | 
			
		||||
  0x6c, 0x61, 0x63, 0x65, 0x28, 0x2f, 0x5f, 0x28, 0x2e, 0x2a, 0x3f, 0x29,
 | 
			
		||||
  0x5f, 0x2f, 0x67, 0x2c, 0x20, 0x27, 0x3c, 0x65, 0x6d, 0x3e, 0x24, 0x31,
 | 
			
		||||
  0x3c, 0x2f, 0x65, 0x6d, 0x3e, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x2e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x2f, 0x60, 0x60,
 | 
			
		||||
  0x60, 0x2e, 0x2a, 0x3f, 0x5c, 0x6e, 0x28, 0x5b, 0x5c, 0x73, 0x5c, 0x53,
 | 
			
		||||
  0x5d, 0x2a, 0x3f, 0x29, 0x60, 0x60, 0x60, 0x2f, 0x67, 0x2c, 0x20, 0x27,
 | 
			
		||||
  0x3c, 0x70, 0x72, 0x65, 0x3e, 0x3c, 0x63, 0x6f, 0x64, 0x65, 0x3e, 0x24,
 | 
			
		||||
  0x31, 0x3c, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x3e, 0x3c, 0x2f, 0x70, 0x72,
 | 
			
		||||
  0x65, 0x3e, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x72, 0x65,
 | 
			
		||||
  0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x2f, 0x60, 0x28, 0x2e, 0x2a, 0x3f,
 | 
			
		||||
  0x29, 0x60, 0x2f, 0x67, 0x2c, 0x20, 0x27, 0x3c, 0x63, 0x6f, 0x64, 0x65,
 | 
			
		||||
  0x3e, 0x24, 0x31, 0x3c, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x3e, 0x27, 0x29,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63,
 | 
			
		||||
  0x65, 0x28, 0x2f, 0x5c, 0x6e, 0x2f, 0x67, 0x69, 0x6d, 0x2c, 0x20, 0x27,
 | 
			
		||||
  0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x27, 0x29, 0x3b, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x68, 0x74, 0x6d, 0x6c, 0x60,
 | 
			
		||||
  0x3c, 0x73, 0x70, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6e, 0x67, 0x65, 0x72,
 | 
			
		||||
  0x6f, 0x75, 0x73, 0x6c, 0x79, 0x53, 0x65, 0x74, 0x49, 0x6e, 0x6e, 0x65,
 | 
			
		||||
  0x72, 0x48, 0x54, 0x4d, 0x4c, 0x3d, 0x24, 0x7b, 0x7b, 0x20, 0x5f, 0x5f,
 | 
			
		||||
  0x68, 0x74, 0x6d, 0x6c, 0x3a, 0x20, 0x6d, 0x64, 0x20, 0x7d, 0x7d, 0x20,
 | 
			
		||||
  0x2f, 0x3e, 0x60, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x70,
 | 
			
		||||
  0x70, 0x28, 0x70, 0x72, 0x6f, 0x70, 0x73, 0x29, 0x20, 0x7b, 0x0a, 0x0a,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
 | 
			
		||||
  0x20, 0x68, 0x74, 0x6d, 0x6c, 0x60, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x6f,
 | 
			
		||||
  0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x22, 0x3e, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x65,
 | 
			
		||||
  0x72, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x3c, 0x68, 0x31, 0x3e, 0x6c, 0x6c, 0x61, 0x6d, 0x61, 0x2e, 0x63,
 | 
			
		||||
  0x70, 0x70, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72,
 | 
			
		||||
  0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x6d, 0x61, 0x69, 0x6e, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x6f, 0x6e,
 | 
			
		||||
  0x74, 0x65, 0x6e, 0x74, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x24, 0x7b, 0x63, 0x68, 0x61, 0x74,
 | 
			
		||||
  0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x2e, 0x76, 0x61, 0x6c, 0x75,
 | 
			
		||||
  0x65, 0x20, 0x3f, 0x20, 0x43, 0x68, 0x61, 0x74, 0x4c, 0x6f, 0x67, 0x20,
 | 
			
		||||
  0x3a, 0x20, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6f, 0x72, 0x6d,
 | 
			
		||||
  0x7d, 0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x3c, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x3e, 0x0a, 0x0a, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x66, 0x6f, 0x6f, 0x74, 0x65,
 | 
			
		||||
  0x72, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x77, 0x72, 0x69, 0x74, 0x65, 0x22,
 | 
			
		||||
  0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x3c, 0x24, 0x7b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x49, 0x6e,
 | 
			
		||||
  0x70, 0x75, 0x74, 0x7d, 0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72,
 | 
			
		||||
  0x3e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c,
 | 
			
		||||
  0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x70, 0x3e, 0x50, 0x6f, 0x77,
 | 
			
		||||
  0x65, 0x72, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x3c, 0x61, 0x20, 0x68,
 | 
			
		||||
  0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f,
 | 
			
		||||
  0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
 | 
			
		||||
  0x67, 0x67, 0x65, 0x72, 0x67, 0x61, 0x6e, 0x6f, 0x76, 0x2f, 0x6c, 0x6c,
 | 
			
		||||
  0x61, 0x6d, 0x61, 0x2e, 0x63, 0x70, 0x70, 0x22, 0x3e, 0x6c, 0x6c, 0x61,
 | 
			
		||||
  0x6d, 0x61, 0x2e, 0x63, 0x70, 0x70, 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x61,
 | 
			
		||||
  0x6e, 0x64, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22,
 | 
			
		||||
  0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x67, 0x67, 0x6d, 0x6c,
 | 
			
		||||
  0x2e, 0x61, 0x69, 0x22, 0x3e, 0x67, 0x67, 0x6d, 0x6c, 0x2e, 0x61, 0x69,
 | 
			
		||||
  0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x2f, 0x70, 0x3e, 0x0a, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65,
 | 
			
		||||
  0x72, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x64,
 | 
			
		||||
  0x69, 0x76, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0x3b,
 | 
			
		||||
  0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
 | 
			
		||||
  0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x28, 0x68, 0x28, 0x41, 0x70, 0x70,
 | 
			
		||||
  0x29, 0x2c, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e,
 | 
			
		||||
  0x62, 0x6f, 0x64, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x3c, 0x2f, 0x73,
 | 
			
		||||
  0x63, 0x72, 0x69, 0x70, 0x74, 0x3e, 0x0a, 0x3c, 0x2f, 0x68, 0x65, 0x61,
 | 
			
		||||
  0x64, 0x3e, 0x0a, 0x0a, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x0a, 0x3c,
 | 
			
		||||
  0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x0a, 0x0a, 0x3c, 0x2f, 0x68, 0x74,
 | 
			
		||||
  0x6d, 0x6c, 0x3e, 0x0a
 | 
			
		||||
};
 | 
			
		||||
unsigned int index_html_len = 10108;
 | 
			
		||||
							
								
								
									
										1851
									
								
								examples/server/index.js.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1851
									
								
								examples/server/index.js.hpp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										81
									
								
								examples/server/public/completion.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								examples/server/public/completion.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
const paramDefaults = {
 | 
			
		||||
  stream: true,
 | 
			
		||||
  n_predict: 500,
 | 
			
		||||
  temperature: 0.2,
 | 
			
		||||
  stop: ["</s>"]
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This function completes the input text using a llama dictionary.
 | 
			
		||||
 * @param {object} params - The parameters for the completion request.
 | 
			
		||||
 * @param {object} controller - an instance of AbortController if you need one, or null.
 | 
			
		||||
 * @param {function} callback - The callback function to call when the completion is done.
 | 
			
		||||
 * @returns {string} the completed text as a string. Ideally ignored, and you get at it via the callback.
 | 
			
		||||
 */
 | 
			
		||||
export const llamaComplete = async (params, controller, callback) => {
 | 
			
		||||
  if (!controller) {
 | 
			
		||||
    controller = new AbortController();
 | 
			
		||||
  }
 | 
			
		||||
  const completionParams = { ...paramDefaults, ...params };
 | 
			
		||||
 | 
			
		||||
  // we use fetch directly here becasue the built in fetchEventSource does not support POST
 | 
			
		||||
  const response = await fetch("/completion", {
 | 
			
		||||
    method: 'POST',
 | 
			
		||||
    body: JSON.stringify(completionParams),
 | 
			
		||||
    headers: {
 | 
			
		||||
      'Connection': 'keep-alive',
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
      'Accept': 'text/event-stream'
 | 
			
		||||
    },
 | 
			
		||||
    signal: controller.signal,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  const reader = response.body.getReader();
 | 
			
		||||
  const decoder = new TextDecoder();
 | 
			
		||||
 | 
			
		||||
  let content = "";
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
 | 
			
		||||
    let cont = true;
 | 
			
		||||
 | 
			
		||||
    while (cont) {
 | 
			
		||||
      const result = await reader.read();
 | 
			
		||||
      if (result.done) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // sse answers in the form multiple lines of: value\n with data always present as a key. in our case we
 | 
			
		||||
      // mainly care about the data: key here, which we expect as json
 | 
			
		||||
      const text = decoder.decode(result.value);
 | 
			
		||||
 | 
			
		||||
      // parse all sse events and add them to result
 | 
			
		||||
      const regex = /^(\S+):\s(.*)$/gm;
 | 
			
		||||
      for (const match of text.matchAll(regex)) {
 | 
			
		||||
        result[match[1]] = match[2]
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // since we know this is llama.cpp, let's just decode the json in data
 | 
			
		||||
      result.data = JSON.parse(result.data);
 | 
			
		||||
      content += result.data.content;
 | 
			
		||||
 | 
			
		||||
      // callack
 | 
			
		||||
      if (callback) {
 | 
			
		||||
        cont = callback(result) != false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // if we got a stop token from server, we will break here
 | 
			
		||||
      if (result.data.stop) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    console.error("llama error: ", e);
 | 
			
		||||
    throw e;
 | 
			
		||||
  }
 | 
			
		||||
  finally {
 | 
			
		||||
    controller.abort();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return content;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										359
									
								
								examples/server/public/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										359
									
								
								examples/server/public/index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,359 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
  <meta charset="UTF-8">
 | 
			
		||||
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
 | 
			
		||||
  <title>llama.cpp - chat</title>
 | 
			
		||||
 | 
			
		||||
  <style>
 | 
			
		||||
 | 
			
		||||
    body {
 | 
			
		||||
      background-color: #fff;
 | 
			
		||||
      color: #000;
 | 
			
		||||
      font-family: system-ui;
 | 
			
		||||
      font-size: 90%;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #container {
 | 
			
		||||
      margin: 0em auto;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
      height: 100%;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    header, footer {
 | 
			
		||||
      text-align: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    main {
 | 
			
		||||
      margin: 3px;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      justify-content: space-between;
 | 
			
		||||
      gap: 1em;
 | 
			
		||||
 | 
			
		||||
      flex-grow: 1;
 | 
			
		||||
      overflow-y: auto;
 | 
			
		||||
 | 
			
		||||
      border: 1px solid #ccc;
 | 
			
		||||
      border-radius: 5px;
 | 
			
		||||
      padding: 0.5em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    body {
 | 
			
		||||
      max-width: 600px;
 | 
			
		||||
      min-width: 300px;
 | 
			
		||||
      line-height: 1.2;
 | 
			
		||||
      margin: 0 auto;
 | 
			
		||||
      padding: 0 0.5em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    p {
 | 
			
		||||
      overflow-wrap: break-word;
 | 
			
		||||
      word-wrap: break-word;
 | 
			
		||||
      hyphens: auto;
 | 
			
		||||
      margin-top: 0.5em;
 | 
			
		||||
      margin-bottom: 0.5em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #write form {
 | 
			
		||||
      margin: 1em 0 0 0;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: column;
 | 
			
		||||
      gap: 0.5em;
 | 
			
		||||
      align-items: stretch;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .right {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-direction: row;
 | 
			
		||||
      gap: 0.5em;
 | 
			
		||||
      justify-content: flex-end;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fieldset {
 | 
			
		||||
      border: none;
 | 
			
		||||
      padding: 0;
 | 
			
		||||
      margin: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    textarea {
 | 
			
		||||
      padding: 5px;
 | 
			
		||||
      flex-grow: 1;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pre code {
 | 
			
		||||
      display: block;
 | 
			
		||||
      background-color: #222;
 | 
			
		||||
      color: #ddd;
 | 
			
		||||
    }
 | 
			
		||||
    code {
 | 
			
		||||
      font-family: monospace;
 | 
			
		||||
      padding: 0.1em 0.3em;
 | 
			
		||||
      border-radius: 3px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fieldset label {
 | 
			
		||||
      margin: 0.5em 0;
 | 
			
		||||
      display: block;
 | 
			
		||||
    }
 | 
			
		||||
  </style>
 | 
			
		||||
 | 
			
		||||
  <script type="module">
 | 
			
		||||
    import {
 | 
			
		||||
      html, h, signal, effect, computed, render, useSignal, useEffect, useRef
 | 
			
		||||
    } from '/index.js';
 | 
			
		||||
 | 
			
		||||
    import { llamaComplete } from '/completion.js';
 | 
			
		||||
 | 
			
		||||
    const session = signal({
 | 
			
		||||
      prompt: "This is a conversation between user and llama, a friendly chatbot. respond in markdown.",
 | 
			
		||||
      template: "{{prompt}}\n\n{{history}}\n{{char}}:",
 | 
			
		||||
      historyTemplate: "{{name}}: {{message}}",
 | 
			
		||||
      transcript: [],
 | 
			
		||||
      type: "chat",
 | 
			
		||||
      char: "llama",
 | 
			
		||||
      user: "User",
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const transcriptUpdate = (transcript) => {
 | 
			
		||||
      session.value = {
 | 
			
		||||
        ...session.value,
 | 
			
		||||
        transcript
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const chatStarted = computed(() => session.value.transcript.length > 0)
 | 
			
		||||
 | 
			
		||||
    const params = signal({
 | 
			
		||||
      n_predict: 400,
 | 
			
		||||
      temperature: 0.7,
 | 
			
		||||
      repeat_last_n: 256,
 | 
			
		||||
      repeat_penalty: 1.18,
 | 
			
		||||
      top_k: 40,
 | 
			
		||||
      top_p: 0.5,
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const controller = signal(null)
 | 
			
		||||
    const generating = computed(() => controller.value == null )
 | 
			
		||||
 | 
			
		||||
    // simple template replace
 | 
			
		||||
    const template = (str, extraSettings) => {
 | 
			
		||||
      let settings = session.value;
 | 
			
		||||
      if (extraSettings) {
 | 
			
		||||
        settings = { ...settings, ...extraSettings };
 | 
			
		||||
      }
 | 
			
		||||
      return String(str).replaceAll(/\{\{(.*?)\}\}/g, (_, key) => template(settings[key]));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // send message to server
 | 
			
		||||
    const chat = async (msg) => {
 | 
			
		||||
      if (controller.value) {
 | 
			
		||||
        console.log('already running...');
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      controller.value = new AbortController();
 | 
			
		||||
 | 
			
		||||
      transcriptUpdate([...session.value.transcript, ["{{user}}", msg]])
 | 
			
		||||
 | 
			
		||||
      const payload = template(session.value.template, {
 | 
			
		||||
        message: msg,
 | 
			
		||||
        history: session.value.transcript.flatMap(([name, message]) => template(session.value.historyTemplate, {name, message})).join("\n"),
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      let currentMessage = '';
 | 
			
		||||
      const history = session.value.transcript
 | 
			
		||||
 | 
			
		||||
      const llamaParams = {
 | 
			
		||||
        ...params.value,
 | 
			
		||||
        prompt: payload,
 | 
			
		||||
        stop: ["</s>", template("{{char}}:"), template("{{user}}:")],
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      await llamaComplete(llamaParams, controller.value, (message) => {
 | 
			
		||||
        const data = message.data;
 | 
			
		||||
        currentMessage += data.content;
 | 
			
		||||
        // remove leading whitespace
 | 
			
		||||
        currentMessage = currentMessage.replace(/^\s+/, "")
 | 
			
		||||
 | 
			
		||||
        transcriptUpdate([...history, ["{{char}}", currentMessage]])
 | 
			
		||||
 | 
			
		||||
        if (data.stop) {
 | 
			
		||||
          console.log("-->", data, ' response was:', currentMessage, 'transcript state:', session.value.transcript);
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      controller.value = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function MessageInput() {
 | 
			
		||||
      const message = useSignal("")
 | 
			
		||||
 | 
			
		||||
      const stop = (e) => {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        if (controller.value) {
 | 
			
		||||
          controller.value.abort();
 | 
			
		||||
          controller.value = null;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const reset = (e) => {
 | 
			
		||||
        stop(e);
 | 
			
		||||
        transcriptUpdate([]);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const submit = (e) => {
 | 
			
		||||
        stop(e);
 | 
			
		||||
        chat(message.value);
 | 
			
		||||
        message.value = "";
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const enterSubmits = (event) => {
 | 
			
		||||
        if (event.which === 13 && !event.shiftKey) {
 | 
			
		||||
          submit(event);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return html`
 | 
			
		||||
        <form onsubmit=${submit}>
 | 
			
		||||
          <div>
 | 
			
		||||
          <textarea type="text" rows=2 onkeypress=${enterSubmits} value="${message}" oninput=${(e) => message.value = e.target.value} placeholder="Say something..."/>
 | 
			
		||||
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="right">
 | 
			
		||||
          <button type="submit" disabled=${!generating.value} >Send</button>
 | 
			
		||||
          <button onclick=${stop} disabled=${generating}>Stop</button>
 | 
			
		||||
          <button onclick=${reset}>Reset</button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </form>
 | 
			
		||||
      `
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const ChatLog = (props) => {
 | 
			
		||||
      const messages = session.value.transcript;
 | 
			
		||||
      const container = useRef(null)
 | 
			
		||||
 | 
			
		||||
      useEffect(() => {
 | 
			
		||||
        // scroll to bottom (if needed)
 | 
			
		||||
        if (container.current && container.current.scrollHeight <= container.current.scrollTop + container.current.offsetHeight + 300) {
 | 
			
		||||
          container.current.scrollTo(0, container.current.scrollHeight)
 | 
			
		||||
        }
 | 
			
		||||
      }, [messages])
 | 
			
		||||
 | 
			
		||||
      const chatLine = ([user, msg]) => {
 | 
			
		||||
        return html`<p key=${msg}><strong>${template(user)}:</strong> <${Markdown} text=${template(msg)} /></p>`
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      return html`
 | 
			
		||||
        <section id="chat" ref=${container}>
 | 
			
		||||
          ${messages.flatMap(chatLine)}
 | 
			
		||||
        </section>`;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const ConfigForm = (props) => {
 | 
			
		||||
      const updateSession = (el) => session.value = { ...session.value, [el.target.name]: el.target.value }
 | 
			
		||||
      const updateParams = (el) => params.value = { ...params.value, [el.target.name]: el.target.value }
 | 
			
		||||
      const updateParamsFloat = (el) => params.value = { ...params.value, [el.target.name]: parseFloat(el.target.value) }
 | 
			
		||||
 | 
			
		||||
      return html`
 | 
			
		||||
        <form>
 | 
			
		||||
          <fieldset>
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="prompt">Prompt</label>
 | 
			
		||||
              <textarea type="text" name="prompt" value="${session.value.prompt}" rows=4 oninput=${updateSession}/>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="user">User name</label>
 | 
			
		||||
              <input type="text" name="user" value="${session.value.user}" oninput=${updateSession} />
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="bot">Bot name</label>
 | 
			
		||||
              <input type="text" name="char" value="${session.value.char}" oninput=${updateSession} />
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="template">Prompt template</label>
 | 
			
		||||
              <textarea id="template" name="template" value="${session.value.template}" rows=4 oninput=${updateSession}/>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="template">Chat history template</label>
 | 
			
		||||
              <textarea id="template" name="historyTemplate" value="${session.value.historyTemplate}" rows=1 oninput=${updateSession}/>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="temperature">Temperature</label>
 | 
			
		||||
              <input type="range" id="temperature" min="0.0" max="1.0" step="0.01" name="temperature" value="${params.value.temperature}" oninput=${updateParamsFloat} />
 | 
			
		||||
              <span>${params.value.temperature}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="nPredict">Predictions</label>
 | 
			
		||||
              <input type="range" id="nPredict" min="1" max="2048" step="1" name="n_predict" value="${params.value.n_predict}" oninput=${updateParamsFloat} />
 | 
			
		||||
              <span>${params.value.n_predict}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="repeat_penalty">Penalize repeat sequence</label>
 | 
			
		||||
              <input type="range" id="repeat_penalty" min="0.0" max="2.0" step="0.01" name="repeat_penalty" value="${params.value.repeat_penalty}" oninput=${updateParamsFloat} />
 | 
			
		||||
              <span>${params.value.repeat_penalty}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div>
 | 
			
		||||
              <label for="repeat_last_n">Consider N tokens for penalize</label>
 | 
			
		||||
              <input type="range" id="repeat_last_n" min="0.0" max="2048" name="repeat_last_n" value="${params.value.repeat_last_n}" oninput=${updateParamsFloat} />
 | 
			
		||||
              <span>${params.value.repeat_last_n}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
          </fieldset>
 | 
			
		||||
        </form>
 | 
			
		||||
      `
 | 
			
		||||
    }
 | 
			
		||||
const Markdown = (params) => {
 | 
			
		||||
  const md = params.text
 | 
			
		||||
    .replace(/^#{1,6} (.*)$/gim, '<h3>$1</h3>')
 | 
			
		||||
    .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
 | 
			
		||||
    .replace(/__(.*?)__/g, '<strong>$1</strong>')
 | 
			
		||||
    .replace(/\*(.*?)\*/g, '<em>$1</em>')
 | 
			
		||||
    .replace(/_(.*?)_/g, '<em>$1</em>')
 | 
			
		||||
    .replace(/```.*?\n([\s\S]*?)```/g, '<pre><code>$1</code></pre>')
 | 
			
		||||
    .replace(/`(.*?)`/g, '<code>$1</code>')
 | 
			
		||||
    .replace(/\n/gim, '<br />');
 | 
			
		||||
  return html`<span dangerouslySetInnerHTML=${{ __html: md }} />`;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    function App(props) {
 | 
			
		||||
 | 
			
		||||
      return html`
 | 
			
		||||
      <div id="container">
 | 
			
		||||
        <header>
 | 
			
		||||
          <h1>llama.cpp</h1>
 | 
			
		||||
        </header>
 | 
			
		||||
 | 
			
		||||
        <main id="content">
 | 
			
		||||
          <${chatStarted.value ? ChatLog : ConfigForm} />
 | 
			
		||||
        </main>
 | 
			
		||||
 | 
			
		||||
        <footer id="write">
 | 
			
		||||
          <${MessageInput} />
 | 
			
		||||
        </footer>
 | 
			
		||||
 | 
			
		||||
        <footer>
 | 
			
		||||
          <p>Powered by <a href="https://github.com/ggerganov/llama.cpp">llama.cpp</a> and <a href="https://ggml.ai">ggml.ai</a></p>
 | 
			
		||||
        </footer>
 | 
			
		||||
      </div>
 | 
			
		||||
      `;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    render(h(App), document.body);
 | 
			
		||||
  </script>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										1
									
								
								examples/server/public/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								examples/server/public/index.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -2,8 +2,6 @@
 | 
			
		||||
#include "llama.h"
 | 
			
		||||
#include "build-info.h"
 | 
			
		||||
 | 
			
		||||
// single thread
 | 
			
		||||
#define CPPHTTPLIB_THREAD_POOL_COUNT 1
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
// crash the server in debug mode, otherwise send an http 500 error
 | 
			
		||||
#define CPPHTTPLIB_NO_EXCEPTIONS 1
 | 
			
		||||
@@ -12,6 +10,11 @@
 | 
			
		||||
#include "httplib.h"
 | 
			
		||||
#include "json.hpp"
 | 
			
		||||
 | 
			
		||||
// auto generated files (update with ./deps.sh)
 | 
			
		||||
#include "index.html.hpp"
 | 
			
		||||
#include "index.js.hpp"
 | 
			
		||||
#include "completion.js.hpp"
 | 
			
		||||
 | 
			
		||||
#ifndef SERVER_VERBOSE
 | 
			
		||||
#define SERVER_VERBOSE 1
 | 
			
		||||
#endif
 | 
			
		||||
@@ -21,11 +24,23 @@ using json = nlohmann::json;
 | 
			
		||||
 | 
			
		||||
struct server_params {
 | 
			
		||||
    std::string hostname = "127.0.0.1";
 | 
			
		||||
    std::string public_path = "examples/server/public";
 | 
			
		||||
    int32_t port = 8080;
 | 
			
		||||
    int32_t read_timeout = 600;
 | 
			
		||||
    int32_t write_timeout = 600;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// completion token output with probabilities
 | 
			
		||||
struct completion_token_output {
 | 
			
		||||
    struct token_prob {
 | 
			
		||||
        llama_token tok;
 | 
			
		||||
        float prob;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    std::vector<token_prob> probs;
 | 
			
		||||
    llama_token tok;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static size_t common_part(const std::vector<llama_token> & a, const std::vector<llama_token> & b) {
 | 
			
		||||
    size_t i;
 | 
			
		||||
    for (i = 0; i < a.size() && i < b.size() && a[i] == b[i]; i++) {}
 | 
			
		||||
@@ -86,6 +101,40 @@ static void server_log(const char * level, const char * function, int line,
 | 
			
		||||
    fflush(stdout);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// format incomplete utf-8 multibyte character for output
 | 
			
		||||
static std::string tokens_to_output_formatted_string(const llama_context * ctx, const llama_token token) {
 | 
			
		||||
    std::string out = token == -1 ? "" : llama_token_to_str(ctx, token);
 | 
			
		||||
    // if first bit is 1, meaning it's a partial character
 | 
			
		||||
    if (out.size() > 0 && (out[0] & 0x80) == 0x80) {
 | 
			
		||||
        std::stringstream ss;
 | 
			
		||||
        ss<< std::hex << (out[0] & 0xff);
 | 
			
		||||
        std::string res ( ss.str() );
 | 
			
		||||
        out = "byte: \\x" + res;
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// convert a vector of completion_token_output to json
 | 
			
		||||
static json probs_vector_to_json(const llama_context * ctx, const std::vector<completion_token_output> probs) {
 | 
			
		||||
    json out = json::array();
 | 
			
		||||
    for (const auto & prob : probs) {
 | 
			
		||||
        json probs_for_token = json::array();
 | 
			
		||||
        for (const auto & p : prob.probs) {
 | 
			
		||||
            std::string tok_str = tokens_to_output_formatted_string(ctx, p.tok);
 | 
			
		||||
            probs_for_token.push_back(json {
 | 
			
		||||
                { "tok_str", tok_str },
 | 
			
		||||
                { "prob", p.prob },
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        std::string tok_str = tokens_to_output_formatted_string(ctx, prob.tok);
 | 
			
		||||
        out.push_back(json {
 | 
			
		||||
            {"content", tok_str},
 | 
			
		||||
            {"probs", probs_for_token},
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool server_verbose = false;
 | 
			
		||||
 | 
			
		||||
#if SERVER_VERBOSE != 1
 | 
			
		||||
@@ -107,7 +156,9 @@ struct llama_server_context {
 | 
			
		||||
    bool stream = false;
 | 
			
		||||
    bool has_next_token = false;
 | 
			
		||||
    std::string generated_text;
 | 
			
		||||
    std::vector<completion_token_output> generated_token_probs;
 | 
			
		||||
 | 
			
		||||
    size_t num_prompt_tokens = 0;
 | 
			
		||||
    size_t num_tokens_predicted = 0;
 | 
			
		||||
    size_t n_past = 0;
 | 
			
		||||
    size_t n_remain = 0;
 | 
			
		||||
@@ -126,6 +177,12 @@ struct llama_server_context {
 | 
			
		||||
    std::string stopping_word;
 | 
			
		||||
    int32_t multibyte_pending = 0;
 | 
			
		||||
 | 
			
		||||
    std::mutex mutex;
 | 
			
		||||
 | 
			
		||||
    std::unique_lock<std::mutex> lock() {
 | 
			
		||||
        return std::unique_lock<std::mutex>(mutex);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~llama_server_context() {
 | 
			
		||||
        if (ctx) {
 | 
			
		||||
            llama_free(ctx);
 | 
			
		||||
@@ -139,9 +196,11 @@ struct llama_server_context {
 | 
			
		||||
 | 
			
		||||
    void rewind() {
 | 
			
		||||
        params.antiprompt.clear();
 | 
			
		||||
        num_prompt_tokens = 0;
 | 
			
		||||
        num_tokens_predicted = 0;
 | 
			
		||||
        generated_text = "";
 | 
			
		||||
        generated_text.reserve(params.n_ctx);
 | 
			
		||||
        generated_token_probs.clear();
 | 
			
		||||
        truncated = false;
 | 
			
		||||
        stopped_eos = false;
 | 
			
		||||
        stopped_word = false;
 | 
			
		||||
@@ -169,17 +228,18 @@ struct llama_server_context {
 | 
			
		||||
    void loadPrompt() {
 | 
			
		||||
        params.prompt.insert(0, 1, ' '); // always add a first space
 | 
			
		||||
        std::vector<llama_token> prompt_tokens = ::llama_tokenize(ctx, params.prompt, true);
 | 
			
		||||
        num_prompt_tokens = prompt_tokens.size();
 | 
			
		||||
 | 
			
		||||
        if (params.n_keep < 0) {
 | 
			
		||||
            params.n_keep = (int)prompt_tokens.size();
 | 
			
		||||
            params.n_keep = (int)num_prompt_tokens;
 | 
			
		||||
        }
 | 
			
		||||
        params.n_keep = std::min(params.n_ctx - 4, params.n_keep);
 | 
			
		||||
 | 
			
		||||
        // if input prompt is too big, truncate like normal
 | 
			
		||||
        if (prompt_tokens.size() >= (size_t)params.n_ctx) {
 | 
			
		||||
        if (num_prompt_tokens>= (size_t)params.n_ctx) {
 | 
			
		||||
            const int n_left = (params.n_ctx - params.n_keep) / 2;
 | 
			
		||||
            std::vector<llama_token> new_tokens(prompt_tokens.begin(), prompt_tokens.begin() + params.n_keep);
 | 
			
		||||
            const int erased_blocks = (prompt_tokens.size() - params.n_keep - n_left - 1) / n_left;
 | 
			
		||||
            const int erased_blocks = (num_prompt_tokens - params.n_keep - n_left - 1) / n_left;
 | 
			
		||||
            new_tokens.insert(new_tokens.end(), prompt_tokens.begin() + params.n_keep + erased_blocks * n_left, prompt_tokens.end());
 | 
			
		||||
            std::copy(prompt_tokens.end() - params.n_ctx, prompt_tokens.end(), last_n_tokens.begin());
 | 
			
		||||
 | 
			
		||||
@@ -193,7 +253,7 @@ struct llama_server_context {
 | 
			
		||||
            truncated = true;
 | 
			
		||||
            prompt_tokens = new_tokens;
 | 
			
		||||
        } else {
 | 
			
		||||
            const size_t ps = prompt_tokens.size();
 | 
			
		||||
            const size_t ps = num_prompt_tokens;
 | 
			
		||||
            std::fill(last_n_tokens.begin(), last_n_tokens.end() - ps, 0);
 | 
			
		||||
            std::copy(prompt_tokens.begin(), prompt_tokens.end(), last_n_tokens.end() - ps);
 | 
			
		||||
        }
 | 
			
		||||
@@ -201,7 +261,7 @@ struct llama_server_context {
 | 
			
		||||
        // compare the evaluated prompt with the new prompt
 | 
			
		||||
        n_past = common_part(embd, prompt_tokens);
 | 
			
		||||
        embd = prompt_tokens;
 | 
			
		||||
        if (n_past == prompt_tokens.size()) {
 | 
			
		||||
        if (n_past == num_prompt_tokens) {
 | 
			
		||||
            // we have to evaluate at least 1 token to generate logits.
 | 
			
		||||
            n_past--;
 | 
			
		||||
        }
 | 
			
		||||
@@ -221,8 +281,9 @@ struct llama_server_context {
 | 
			
		||||
        llama_set_rng_seed(ctx, params.seed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    llama_token nextToken() {
 | 
			
		||||
        llama_token result = -1;
 | 
			
		||||
    completion_token_output nextToken() {
 | 
			
		||||
        completion_token_output result;
 | 
			
		||||
        result.tok = -1;
 | 
			
		||||
 | 
			
		||||
        if (embd.size() >= (size_t)params.n_ctx) {
 | 
			
		||||
            // Reset context
 | 
			
		||||
@@ -261,7 +322,8 @@ struct llama_server_context {
 | 
			
		||||
 | 
			
		||||
        if (params.n_predict == 0) {
 | 
			
		||||
            has_next_token = false;
 | 
			
		||||
            return llama_token_eos();
 | 
			
		||||
            result.tok = llama_token_eos();
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // out of user input, sample next token
 | 
			
		||||
@@ -278,7 +340,7 @@ struct llama_server_context {
 | 
			
		||||
        const float mirostat_tau = params.mirostat_tau;
 | 
			
		||||
        const float mirostat_eta = params.mirostat_eta;
 | 
			
		||||
        const bool penalize_nl = params.penalize_nl;
 | 
			
		||||
        llama_token id = 0;
 | 
			
		||||
        const int32_t n_probs = params.n_probs;
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            auto * logits = llama_get_logits(ctx);
 | 
			
		||||
@@ -312,35 +374,42 @@ struct llama_server_context {
 | 
			
		||||
 | 
			
		||||
            if (temp <= 0) {
 | 
			
		||||
                // Greedy sampling
 | 
			
		||||
                id = llama_sample_token_greedy(ctx, &candidates_p);
 | 
			
		||||
                result.tok = llama_sample_token_greedy(ctx, &candidates_p);
 | 
			
		||||
                if (n_probs > 0) {
 | 
			
		||||
                    llama_sample_softmax(ctx, &candidates_p);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                if (mirostat == 1) {
 | 
			
		||||
                    static float mirostat_mu = 2.0f * mirostat_tau;
 | 
			
		||||
                    const int mirostat_m = 100;
 | 
			
		||||
                    llama_sample_temperature(ctx, &candidates_p, temp);
 | 
			
		||||
                    id = llama_sample_token_mirostat(ctx, &candidates_p, mirostat_tau, mirostat_eta, mirostat_m, &mirostat_mu);
 | 
			
		||||
                    result.tok = llama_sample_token_mirostat(ctx, &candidates_p, mirostat_tau, mirostat_eta, mirostat_m, &mirostat_mu);
 | 
			
		||||
                } else if (mirostat == 2) {
 | 
			
		||||
                    static float mirostat_mu = 2.0f * mirostat_tau;
 | 
			
		||||
                    llama_sample_temperature(ctx, &candidates_p, temp);
 | 
			
		||||
                    id = llama_sample_token_mirostat_v2(ctx, &candidates_p, mirostat_tau, mirostat_eta, &mirostat_mu);
 | 
			
		||||
                    result.tok = llama_sample_token_mirostat_v2(ctx, &candidates_p, mirostat_tau, mirostat_eta, &mirostat_mu);
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Temperature sampling
 | 
			
		||||
                    llama_sample_top_k(ctx, &candidates_p, top_k, 1);
 | 
			
		||||
                    llama_sample_tail_free(ctx, &candidates_p, tfs_z, 1);
 | 
			
		||||
                    llama_sample_typical(ctx, &candidates_p, typical_p, 1);
 | 
			
		||||
                    llama_sample_top_p(ctx, &candidates_p, top_p, 1);
 | 
			
		||||
                    size_t min_keep = std::max(1, n_probs);
 | 
			
		||||
                    llama_sample_top_k(ctx, &candidates_p, top_k, min_keep);
 | 
			
		||||
                    llama_sample_tail_free(ctx, &candidates_p, tfs_z, min_keep);
 | 
			
		||||
                    llama_sample_typical(ctx, &candidates_p, typical_p, min_keep);
 | 
			
		||||
                    llama_sample_top_p(ctx, &candidates_p, top_p, min_keep);
 | 
			
		||||
                    llama_sample_temperature(ctx, &candidates_p, temp);
 | 
			
		||||
                    id = llama_sample_token(ctx, &candidates_p);
 | 
			
		||||
                    result.tok = llama_sample_token(ctx, &candidates_p);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (size_t i = 0; i < std::min(candidates_p.size, (size_t) n_probs); ++i) {
 | 
			
		||||
                result.probs.push_back({candidates_p.data[i].id, candidates_p.data[i].p});
 | 
			
		||||
            }
 | 
			
		||||
            last_n_tokens.erase(last_n_tokens.begin());
 | 
			
		||||
            last_n_tokens.push_back(id);
 | 
			
		||||
            last_n_tokens.push_back(result.tok);
 | 
			
		||||
            num_tokens_predicted++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // add it to the context
 | 
			
		||||
        embd.push_back(id);
 | 
			
		||||
        result = id;
 | 
			
		||||
        embd.push_back(result.tok);
 | 
			
		||||
        // decrement remaining sampling budget
 | 
			
		||||
        --n_remain;
 | 
			
		||||
 | 
			
		||||
@@ -382,12 +451,16 @@ struct llama_server_context {
 | 
			
		||||
        return stop_pos;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string doCompletion() {
 | 
			
		||||
        const llama_token token = nextToken();
 | 
			
		||||
    completion_token_output doCompletion() {
 | 
			
		||||
        const completion_token_output token_with_probs = nextToken();
 | 
			
		||||
 | 
			
		||||
        const std::string token_text = token == -1 ? "" : llama_token_to_str(ctx, token);
 | 
			
		||||
        const std::string token_text = token_with_probs.tok == -1 ? "" : llama_token_to_str(ctx, token_with_probs.tok);
 | 
			
		||||
        generated_text += token_text;
 | 
			
		||||
 | 
			
		||||
        if (params.n_probs > 0) {
 | 
			
		||||
            generated_token_probs.push_back(token_with_probs);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (multibyte_pending > 0) {
 | 
			
		||||
            multibyte_pending -= token_text.size();
 | 
			
		||||
        } else if (token_text.size() == 1) {
 | 
			
		||||
@@ -416,8 +489,8 @@ struct llama_server_context {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        LOG_VERBOSE("next token", {
 | 
			
		||||
            { "token", token },
 | 
			
		||||
            { "token_text", llama_token_to_str(ctx, token) },
 | 
			
		||||
            { "token", token_with_probs.tok },
 | 
			
		||||
            { "token_text", tokens_to_output_formatted_string(ctx, token_with_probs.tok) },
 | 
			
		||||
            { "has_next_token", has_next_token },
 | 
			
		||||
            { "n_remain", n_remain },
 | 
			
		||||
            { "num_tokens_predicted", num_tokens_predicted },
 | 
			
		||||
@@ -427,7 +500,7 @@ struct llama_server_context {
 | 
			
		||||
            { "stopping_word", stopping_word },
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return token_text;
 | 
			
		||||
        return token_with_probs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::vector<float> getEmbedding() {
 | 
			
		||||
@@ -479,6 +552,7 @@ static void server_print_usage(const char * argv0, const gpt_params & params,
 | 
			
		||||
    fprintf(stderr, "  --lora-base FNAME     optional model to use as a base for the layers modified by the LoRA adapter\n");
 | 
			
		||||
    fprintf(stderr, "  --host                ip address to listen (default  (default: %s)\n", sparams.hostname.c_str());
 | 
			
		||||
    fprintf(stderr, "  --port PORT           port to listen (default  (default: %d)\n", sparams.port);
 | 
			
		||||
    fprintf(stderr, "  --path PUBLIC_PATH    path from which to serve static files (default %s)\n", sparams.public_path.c_str());
 | 
			
		||||
    fprintf(stderr, "  -to N, --timeout N    server read/write timeout in seconds (default: %d)\n", sparams.read_timeout);
 | 
			
		||||
    fprintf(stderr, "  --embedding           enable embedding vector output (default: %s)\n", params.embedding ? "enabled" : "disabled");
 | 
			
		||||
    fprintf(stderr, "\n");
 | 
			
		||||
@@ -505,6 +579,12 @@ static void server_params_parse(int argc, char ** argv, server_params & sparams,
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            sparams.hostname = argv[i];
 | 
			
		||||
        } else if (arg == "--path") {
 | 
			
		||||
            if (++i >= argc) {
 | 
			
		||||
                invalid_param = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            sparams.public_path = argv[i];
 | 
			
		||||
        } else if (arg == "--timeout" || arg == "-to") {
 | 
			
		||||
            if (++i >= argc) {
 | 
			
		||||
                invalid_param = true;
 | 
			
		||||
@@ -669,6 +749,7 @@ static json format_generation_settings(llama_server_context & llama) {
 | 
			
		||||
        { "ignore_eos", ignore_eos },
 | 
			
		||||
        { "stream", llama.stream },
 | 
			
		||||
        { "logit_bias", llama.params.logit_bias },
 | 
			
		||||
        { "n_probs", llama.params.n_probs },
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -678,12 +759,14 @@ static json format_embedding_response(llama_server_context & llama) {
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static json format_final_response(llama_server_context & llama, const std::string & content) {
 | 
			
		||||
    return json {
 | 
			
		||||
static json format_final_response(llama_server_context & llama, const std::string & content, const std::vector<completion_token_output> & probs) {
 | 
			
		||||
 | 
			
		||||
    json res = json {
 | 
			
		||||
        { "content", content },
 | 
			
		||||
        { "stop", true },
 | 
			
		||||
        { "model", llama.params.model_alias },
 | 
			
		||||
        { "tokens_predicted", llama.num_tokens_predicted },
 | 
			
		||||
        { "tokens_evaluated", llama.num_prompt_tokens },
 | 
			
		||||
        { "generation_settings", format_generation_settings(llama) },
 | 
			
		||||
        { "prompt", llama.params.prompt },
 | 
			
		||||
        { "truncated", llama.truncated },
 | 
			
		||||
@@ -692,13 +775,25 @@ static json format_final_response(llama_server_context & llama, const std::strin
 | 
			
		||||
        { "stopped_limit", llama.stopped_limit },
 | 
			
		||||
        { "stopping_word", llama.stopping_word },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (llama.params.n_probs > 0) {
 | 
			
		||||
        res["completion_probabilities"] = probs_vector_to_json(llama.ctx, probs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static json format_partial_response(const std::string & content) {
 | 
			
		||||
    return json {
 | 
			
		||||
static json format_partial_response(llama_server_context & llama, const std::string & content, const std::vector<completion_token_output> & probs) {
 | 
			
		||||
    json res = json {
 | 
			
		||||
        { "content", content },
 | 
			
		||||
        { "stop", false },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (llama.params.n_probs > 0) {
 | 
			
		||||
        res["completion_probabilities"] = probs_vector_to_json(llama.ctx, probs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static json format_tokenizer_response(const std::vector<llama_token> & tokens) {
 | 
			
		||||
@@ -728,6 +823,7 @@ static void parse_options_completion(const json & body, llama_server_context & l
 | 
			
		||||
    llama.params.n_keep = body.value("n_keep", default_params.n_keep);
 | 
			
		||||
    llama.params.seed = body.value("seed", default_params.seed);
 | 
			
		||||
    llama.params.prompt = body.value("prompt", default_params.prompt);
 | 
			
		||||
    llama.params.n_probs = body.value("n_probs", default_params.n_probs);
 | 
			
		||||
 | 
			
		||||
    llama.params.logit_bias.clear();
 | 
			
		||||
    if (body.value("ignore_eos", false)) {
 | 
			
		||||
@@ -764,17 +860,24 @@ static void parse_options_completion(const json & body, llama_server_context & l
 | 
			
		||||
    LOG_VERBOSE("completion parameters parsed", format_generation_settings(llama));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void log_server_request(const Request & req, const Response & res) {
 | 
			
		||||
    LOG_INFO("request", {
 | 
			
		||||
        { "remote_addr", req.remote_addr },
 | 
			
		||||
        { "remote_port", req.remote_port },
 | 
			
		||||
        { "status", res.status },
 | 
			
		||||
        { "method", req.method },
 | 
			
		||||
        { "path", req.path },
 | 
			
		||||
        { "params", req.params },
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    LOG_VERBOSE("request", {
 | 
			
		||||
        { "request", req.body },
 | 
			
		||||
        { "response", res.body },
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main(int argc, char ** argv) {
 | 
			
		||||
    // own arguments required by this example
 | 
			
		||||
    gpt_params params;
 | 
			
		||||
@@ -809,16 +912,34 @@ int main(int argc, char ** argv) {
 | 
			
		||||
    Server svr;
 | 
			
		||||
 | 
			
		||||
    svr.set_default_headers({
 | 
			
		||||
        { "Server", "llama.cpp" },
 | 
			
		||||
        { "Access-Control-Allow-Origin", "*" },
 | 
			
		||||
        { "Access-Control-Allow-Headers", "content-type" }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // this is only called if no index.js is found in the public --path
 | 
			
		||||
    svr.Get("/index.js", [](const Request &, Response & res) {
 | 
			
		||||
        res.set_content(reinterpret_cast<const char *>(&index_js), index_js_len, "text/javascript");
 | 
			
		||||
        return false;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // this is only called if no index.html is found in the public --path
 | 
			
		||||
    svr.Get("/", [](const Request &, Response & res) {
 | 
			
		||||
        res.set_content("<h1>llama.cpp server works</h1>", "text/html");
 | 
			
		||||
        res.set_content(reinterpret_cast<const char*>(&index_html), index_html_len, "text/html");
 | 
			
		||||
        return false;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // this is only called if no index.html is found in the public --path
 | 
			
		||||
    svr.Get("/completion.js", [](const Request &, Response & res) {
 | 
			
		||||
        res.set_content(reinterpret_cast<const char*>(&completion_js), completion_js_len, "application/javascript");
 | 
			
		||||
        return false;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    svr.Post("/completion", [&llama](const Request & req, Response & res) {
 | 
			
		||||
        auto lock = llama.lock();
 | 
			
		||||
 | 
			
		||||
        llama.rewind();
 | 
			
		||||
 | 
			
		||||
        llama_reset_timings(llama.ctx);
 | 
			
		||||
 | 
			
		||||
        parse_options_completion(json::parse(req.body), llama);
 | 
			
		||||
@@ -830,7 +951,8 @@ int main(int argc, char ** argv) {
 | 
			
		||||
            size_t stop_pos = std::string::npos;
 | 
			
		||||
 | 
			
		||||
            while (llama.has_next_token) {
 | 
			
		||||
                const std::string token_text = llama.doCompletion();
 | 
			
		||||
                const completion_token_output token_with_probs = llama.doCompletion();
 | 
			
		||||
                const std::string token_text = token_with_probs.tok == -1 ? "" : llama_token_to_str(llama.ctx, token_with_probs.tok);
 | 
			
		||||
 | 
			
		||||
                stop_pos = llama.findStoppingStrings(llama.generated_text,
 | 
			
		||||
                    token_text.size(), STOP_FULL);
 | 
			
		||||
@@ -844,7 +966,7 @@ int main(int argc, char ** argv) {
 | 
			
		||||
                    llama.generated_text.end());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const json data = format_final_response(llama, llama.generated_text);
 | 
			
		||||
            const json data = format_final_response(llama, llama.generated_text, llama.generated_token_probs);
 | 
			
		||||
 | 
			
		||||
            llama_print_timings(llama.ctx);
 | 
			
		||||
 | 
			
		||||
@@ -853,9 +975,11 @@ int main(int argc, char ** argv) {
 | 
			
		||||
        } else {
 | 
			
		||||
            const auto chunked_content_provider = [&](size_t, DataSink & sink) {
 | 
			
		||||
                size_t sent_count = 0;
 | 
			
		||||
                size_t sent_token_probs_index = 0;
 | 
			
		||||
 | 
			
		||||
                while (llama.has_next_token) {
 | 
			
		||||
                    const std::string token_text = llama.doCompletion();
 | 
			
		||||
                    const completion_token_output token_with_probs = llama.doCompletion();
 | 
			
		||||
                    const std::string token_text = token_with_probs.tok == -1 ? "" : llama_token_to_str(llama.ctx, token_with_probs.tok);
 | 
			
		||||
                    if (llama.multibyte_pending > 0) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
@@ -878,10 +1002,22 @@ int main(int argc, char ** argv) {
 | 
			
		||||
                    const std::string to_send = llama.generated_text.substr(pos, stop_pos);
 | 
			
		||||
                    sent_count += to_send.size();
 | 
			
		||||
 | 
			
		||||
                    std::vector<completion_token_output> probs_output = {};
 | 
			
		||||
 | 
			
		||||
                    if (llama.params.n_probs > 0) {
 | 
			
		||||
                        const std::vector<llama_token> to_send_toks = llama_tokenize(llama.ctx, to_send, false);
 | 
			
		||||
                        size_t probs_pos = std::min(sent_token_probs_index, llama.generated_token_probs.size());
 | 
			
		||||
                        size_t probs_stop_pos = std::min(sent_token_probs_index + to_send_toks.size(), llama.generated_token_probs.size());
 | 
			
		||||
                        if (probs_pos < probs_stop_pos) {
 | 
			
		||||
                            probs_output = std::vector<completion_token_output>(llama.generated_token_probs.begin() + probs_pos, llama.generated_token_probs.begin() + probs_stop_pos);
 | 
			
		||||
                        }
 | 
			
		||||
                        sent_token_probs_index = probs_stop_pos;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    const json data = llama.has_next_token
 | 
			
		||||
                                          ? format_partial_response(to_send)
 | 
			
		||||
                                          ? format_partial_response(llama, to_send, probs_output)
 | 
			
		||||
                                          // Generation is done, send extra information.
 | 
			
		||||
                                          : format_final_response(llama, to_send);
 | 
			
		||||
                                          : format_final_response(llama, to_send, llama.generated_token_probs);
 | 
			
		||||
 | 
			
		||||
                    const std::string str =
 | 
			
		||||
                        "data: " +
 | 
			
		||||
@@ -912,6 +1048,8 @@ int main(int argc, char ** argv) {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    svr.Post("/tokenize", [&llama](const Request & req, Response & res) {
 | 
			
		||||
        auto lock = llama.lock();
 | 
			
		||||
 | 
			
		||||
        const json body = json::parse(req.body);
 | 
			
		||||
        const std::string content = body.value("content", "");
 | 
			
		||||
        const std::vector<llama_token> tokens = llama_tokenize(llama.ctx, content, false);
 | 
			
		||||
@@ -920,6 +1058,8 @@ int main(int argc, char ** argv) {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    svr.Post("/embedding", [&llama](const Request & req, Response & res) {
 | 
			
		||||
        auto lock = llama.lock();
 | 
			
		||||
 | 
			
		||||
        const json body = json::parse(req.body);
 | 
			
		||||
 | 
			
		||||
        llama.rewind();
 | 
			
		||||
@@ -950,18 +1090,27 @@ int main(int argc, char ** argv) {
 | 
			
		||||
        res.status = 500;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    svr.set_error_handler([](const Request &, Response & res) {
 | 
			
		||||
        res.set_content("File Not Found", "text/plain");
 | 
			
		||||
        res.status = 404;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // set timeouts and change hostname and port
 | 
			
		||||
    svr.set_read_timeout(sparams.read_timeout);
 | 
			
		||||
    svr.set_write_timeout(sparams.write_timeout);
 | 
			
		||||
 | 
			
		||||
    if (!svr.bind_to_port(sparams.hostname, sparams.port)) {
 | 
			
		||||
        LOG_ERROR("couldn't bind to server socket", {
 | 
			
		||||
            { "hostname", sparams.hostname },
 | 
			
		||||
            { "port", sparams.port },
 | 
			
		||||
        });
 | 
			
		||||
        fprintf(stderr, "\ncouldn't bind to server socket: hostname=%s port=%d\n\n", sparams.hostname.c_str(), sparams.port);
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Set the base directory for serving static files
 | 
			
		||||
    svr.set_base_dir(sparams.public_path);
 | 
			
		||||
 | 
			
		||||
    // to make it ctrl+clickable:
 | 
			
		||||
    fprintf(stdout, "\nllama server listening at http://%s:%d\n\n", sparams.hostname.c_str(), sparams.port);
 | 
			
		||||
 | 
			
		||||
    LOG_INFO("HTTP server listening", {
 | 
			
		||||
        { "hostname", sparams.hostname },
 | 
			
		||||
        { "port", sparams.port },
 | 
			
		||||
 
 | 
			
		||||
@@ -2835,7 +2835,7 @@ void ggml_cuda_transform_tensor(void * data, struct ggml_tensor * tensor) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ggml_cuda_free_data(struct ggml_tensor * tensor) {
 | 
			
		||||
    if (tensor->backend != GGML_BACKEND_GPU && tensor->backend != GGML_BACKEND_GPU_SPLIT) {
 | 
			
		||||
    if (!tensor || (tensor->backend != GGML_BACKEND_GPU && tensor->backend != GGML_BACKEND_GPU_SPLIT) ) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1376,7 +1376,7 @@ static void ggml_cl_mul_f32(const ggml_tensor * src0, const ggml_tensor * src1,
 | 
			
		||||
    const int64_t ne00 = src0->ne[0];
 | 
			
		||||
    const int64_t ne01 = src0->ne[1];
 | 
			
		||||
    const int64_t ne02 = src0->ne[2];
 | 
			
		||||
    const int64_t ne03 = src0->ne[2];
 | 
			
		||||
    const int64_t ne03 = src0->ne[3];
 | 
			
		||||
    const int64_t ne0 = ne00 * ne01 * ne02 * ne03;
 | 
			
		||||
    const int64_t ne10 = src1->ne[0];
 | 
			
		||||
    const int64_t ne11 = src1->ne[1];
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										118
									
								
								ggml.h
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								ggml.h
									
									
									
									
									
								
							@@ -201,6 +201,8 @@
 | 
			
		||||
#define GGML_MAX_NAME          48
 | 
			
		||||
#define GGML_DEFAULT_N_THREADS 4
 | 
			
		||||
 | 
			
		||||
#define GGML_UNUSED(x) (void)(x)
 | 
			
		||||
 | 
			
		||||
#define GGML_ASSERT(x) \
 | 
			
		||||
    do { \
 | 
			
		||||
        if (!(x)) { \
 | 
			
		||||
@@ -209,6 +211,30 @@
 | 
			
		||||
        } \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
// used to copy the number of elements and stride in bytes of tensors into local variables.
 | 
			
		||||
// main purpose is to reduce code duplication and improve readability.
 | 
			
		||||
//
 | 
			
		||||
// example:
 | 
			
		||||
//
 | 
			
		||||
//    GGML_TENSOR_LOCALS(int64_t, ne1, src1, ne);
 | 
			
		||||
//    GGML_TENSOR_LOCALS(size_t,  nb1, src1, nb);
 | 
			
		||||
//
 | 
			
		||||
#define GGML_TENSOR_LOCALS_1(type, prefix, pointer, array) \
 | 
			
		||||
    const type prefix##0 = (pointer)->array[0]; \
 | 
			
		||||
    GGML_UNUSED(prefix##0);
 | 
			
		||||
#define GGML_TENSOR_LOCALS_2(type, prefix, pointer, array) \
 | 
			
		||||
    GGML_TENSOR_LOCALS_1    (type, prefix, pointer, array) \
 | 
			
		||||
    const type prefix##1 = (pointer)->array[1]; \
 | 
			
		||||
    GGML_UNUSED(prefix##1);
 | 
			
		||||
#define GGML_TENSOR_LOCALS_3(type, prefix, pointer, array) \
 | 
			
		||||
    GGML_TENSOR_LOCALS_2    (type, prefix, pointer, array) \
 | 
			
		||||
    const type prefix##2 = (pointer)->array[2]; \
 | 
			
		||||
    GGML_UNUSED(prefix##2);
 | 
			
		||||
#define GGML_TENSOR_LOCALS(type, prefix, pointer, array) \
 | 
			
		||||
    GGML_TENSOR_LOCALS_3  (type, prefix, pointer, array) \
 | 
			
		||||
    const type prefix##3 = (pointer)->array[3]; \
 | 
			
		||||
    GGML_UNUSED(prefix##3);
 | 
			
		||||
 | 
			
		||||
#ifdef  __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
@@ -295,12 +321,15 @@ extern "C" {
 | 
			
		||||
        GGML_OP_SUM,
 | 
			
		||||
        GGML_OP_SUM_ROWS,
 | 
			
		||||
        GGML_OP_MEAN,
 | 
			
		||||
        GGML_OP_ARGMAX,
 | 
			
		||||
        GGML_OP_REPEAT,
 | 
			
		||||
        GGML_OP_REPEAT_BACK,
 | 
			
		||||
        GGML_OP_ABS,
 | 
			
		||||
        GGML_OP_SGN,
 | 
			
		||||
        GGML_OP_NEG,
 | 
			
		||||
        GGML_OP_STEP,
 | 
			
		||||
        GGML_OP_TANH,
 | 
			
		||||
        GGML_OP_ELU,
 | 
			
		||||
        GGML_OP_RELU,
 | 
			
		||||
        GGML_OP_GELU,
 | 
			
		||||
        GGML_OP_GELU_QUICK,
 | 
			
		||||
@@ -332,9 +361,8 @@ extern "C" {
 | 
			
		||||
        GGML_OP_ROPE_BACK,
 | 
			
		||||
        GGML_OP_ALIBI,
 | 
			
		||||
        GGML_OP_CLAMP,
 | 
			
		||||
        GGML_OP_CONV_1D_S1_PH,
 | 
			
		||||
        GGML_OP_CONV_1D_S2_PH,
 | 
			
		||||
        GGML_OP_CONV_2D_SK_P0,
 | 
			
		||||
        GGML_OP_CONV_1D,
 | 
			
		||||
        GGML_OP_CONV_2D,
 | 
			
		||||
 | 
			
		||||
        GGML_OP_FLASH_ATTN,
 | 
			
		||||
        GGML_OP_FLASH_FF,
 | 
			
		||||
@@ -690,6 +718,11 @@ extern "C" {
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a);
 | 
			
		||||
 | 
			
		||||
    // argmax along rows
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_argmax(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a);
 | 
			
		||||
 | 
			
		||||
    // if a is the same shape as b, and a is not parameter, return a
 | 
			
		||||
    // otherwise, return a new tensor: repeat(a) to fit in b
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_repeat(
 | 
			
		||||
@@ -734,6 +767,22 @@ extern "C" {
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a);
 | 
			
		||||
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_tanh(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a);
 | 
			
		||||
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_tanh_inplace(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a);
 | 
			
		||||
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_elu(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a);
 | 
			
		||||
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_elu_inplace(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a);
 | 
			
		||||
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_relu(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a);
 | 
			
		||||
@@ -1084,58 +1133,33 @@ extern "C" {
 | 
			
		||||
            float                 min,
 | 
			
		||||
            float                 max);
 | 
			
		||||
 | 
			
		||||
    // TODO: implement general-purpose convolutions
 | 
			
		||||
    // GGML_API struct ggml_tensor * ggml_conv_1d(
 | 
			
		||||
    //        struct ggml_context * ctx,
 | 
			
		||||
    //        struct ggml_tensor  * a,
 | 
			
		||||
    //        struct ggml_tensor  * b,
 | 
			
		||||
    //        int                   s0
 | 
			
		||||
    //        int                   p0,
 | 
			
		||||
    //        int                   d0);
 | 
			
		||||
    //
 | 
			
		||||
    // GGML_API struct ggml_tensor * ggml_conv_2d(
 | 
			
		||||
    //        struct ggml_context * ctx,
 | 
			
		||||
    //        struct ggml_tensor  * a,
 | 
			
		||||
    //        struct ggml_tensor  * b,
 | 
			
		||||
    //        int                   s0,
 | 
			
		||||
    //        int                   s1,
 | 
			
		||||
    //        int                   p0,
 | 
			
		||||
    //        int                   p1,
 | 
			
		||||
    //        int                   d0,
 | 
			
		||||
    //        int                   d1);
 | 
			
		||||
 | 
			
		||||
    // padding = half
 | 
			
		||||
    // TODO: we don't support extra parameters for now
 | 
			
		||||
    //       that's why we are hard-coding the stride, padding, and dilation
 | 
			
		||||
    //       not great ..
 | 
			
		||||
    // example:
 | 
			
		||||
    // a:      3   80  768    1
 | 
			
		||||
    // b:   3000   80    1    1
 | 
			
		||||
    // res: 3000  768    1    1
 | 
			
		||||
    // used in whisper
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_conv_1d_s1_ph(
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_conv_1d(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a,
 | 
			
		||||
            struct ggml_tensor  * b);
 | 
			
		||||
            struct ggml_tensor  * b,
 | 
			
		||||
            int                   s0,  // stride
 | 
			
		||||
            int                   p0,  // padding
 | 
			
		||||
            int                   d0); // dilation
 | 
			
		||||
 | 
			
		||||
    // used in whisper
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_conv_1d_s2_ph(
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_conv_2d(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a,
 | 
			
		||||
            struct ggml_tensor  * b);
 | 
			
		||||
            struct ggml_tensor  * b,
 | 
			
		||||
            int                   s0,
 | 
			
		||||
            int                   s1,
 | 
			
		||||
            int                   p0,
 | 
			
		||||
            int                   p1,
 | 
			
		||||
            int                   d0,
 | 
			
		||||
            int                   d1);
 | 
			
		||||
 | 
			
		||||
    // kernel size is a->ne[0] x a->ne[1]
 | 
			
		||||
    // stride is equal to kernel size
 | 
			
		||||
    // padding is zero
 | 
			
		||||
    // example:
 | 
			
		||||
    // a:     16   16    3  768
 | 
			
		||||
    // b:   1024 1024    3    1
 | 
			
		||||
    // res:   64   64  768    1
 | 
			
		||||
    // used in sam
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_conv_2d_sk_p0(
 | 
			
		||||
    // conv_1d with padding = half
 | 
			
		||||
    // alias for ggml_conv_1d(a, b, s, a->ne[0]/2, d)
 | 
			
		||||
    GGML_API struct ggml_tensor* ggml_conv_1d_ph(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
            struct ggml_tensor  * a,
 | 
			
		||||
            struct ggml_tensor  * b);
 | 
			
		||||
            struct ggml_tensor  * b,
 | 
			
		||||
            int                   s,
 | 
			
		||||
            int                   d);
 | 
			
		||||
 | 
			
		||||
    GGML_API struct ggml_tensor * ggml_flash_attn(
 | 
			
		||||
            struct ggml_context * ctx,
 | 
			
		||||
 
 | 
			
		||||
@@ -194,8 +194,8 @@ struct llama_layer {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct llama_kv_cache {
 | 
			
		||||
    struct ggml_tensor * k;
 | 
			
		||||
    struct ggml_tensor * v;
 | 
			
		||||
    struct ggml_tensor * k = NULL;
 | 
			
		||||
    struct ggml_tensor * v = NULL;
 | 
			
		||||
 | 
			
		||||
    struct ggml_context * ctx = NULL;
 | 
			
		||||
 | 
			
		||||
@@ -481,9 +481,7 @@ struct llama_file_loader {
 | 
			
		||||
            std::string word = file.read_string(len);
 | 
			
		||||
 | 
			
		||||
            float score = 0.0f;
 | 
			
		||||
            if (file_version >= LLAMA_FILE_VERSION_GGMF_V1) {
 | 
			
		||||
            file.read_raw(&score, sizeof(score));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            vocab.token_to_id[word] = i;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,11 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
cp -rpv ../ggml/src/ggml.c           ./ggml.c
 | 
			
		||||
cp -rpv ../ggml/src/ggml-cuda.cu    ./ggml-cuda.cu
 | 
			
		||||
cp -rpv ../ggml/src/ggml-cuda.h      ./ggml-cuda.h
 | 
			
		||||
cp -rpv ../ggml/src/ggml-cuda.cu     ./ggml-cuda.cu
 | 
			
		||||
cp -rpv ../ggml/src/ggml-opencl.h    ./ggml-opencl.h
 | 
			
		||||
cp -rpv ../ggml/src/ggml-opencl.cpp  ./ggml-opencl.cpp
 | 
			
		||||
cp -rpv ../ggml/src/ggml-metal.h     ./ggml-metal.h
 | 
			
		||||
cp -rpv ../ggml/src/ggml-metal.m     ./ggml-metal.m
 | 
			
		||||
cp -rpv ../ggml/src/ggml-metal.metal ./ggml-metal.metal
 | 
			
		||||
cp -rpv ../ggml/include/ggml/ggml.h ./ggml.h
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user