MQoyVGVzdCBDb2RlCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwovL0ZpbGU6ICAgIGxpbmVGb2xsb3czLmljCQovL1JvYnVzdCAgIDA0LzE4LzIwMTIKLy9QdXJwb3NlOiBCcnV0ZSBmb3JjZSB0byBoYXZlIHJvdmVyIGZvbGxvdyBhIGxpbmUgKH4yLjUgaW5jaGVzIHdpZGUpCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKaW50IHBjdE1PVE9SX1BPV0VSICAgPSA5MDsgIC8vcG93ZXIgbGV2ZWwgZm9yIG1vdG9ycwppbnQgd2FzRm9sbG93aW5nTGluZSA9IDA7ICAgLy91c2VkIHdoZW4gb2ZmIGNvdXJzZSAobm90IG9uIGxpbmUpCgovL2RpcmVjdGlvbiByb3ZlciB3YXMgbGFzdCBnb2luZyAoMD1ub25lLDE9Zm9yd2FyZCwyPWxlZnQsMz1yaWdodCkKaW50IGxhc3RNb3ZlICAgICAgICAgPSAwOyAgIAoKLy9TdGF0ZXMgdGhlIHJvdmVyIGNhbiBiZSBpbiwgYXMgaW50ZXJwcmV0ZWQgZnJvbSB0aGUgc2Vuc29yIHZhbHVlcwojZGVmaW5lIG9uTGluZSAgICAgICAxICAvL3N0YXRlIGluZGljYXRpdmUgb2YgbG93UmVhZCBmcm9tIFNlbnNvcnMKI2RlZmluZSBzcGFjZUluc2lnaHQgMiAgLy9zdGF0ZSBpbmRpY2F0aXZlIG9mIG1pZFJlYWQgZnJvbSBTZW5zb3JzCiNkZWZpbmUgbGluZUluc2lnaHQgIDMgIC8vc3RhdGUgaW5kaWNhdGl2ZSBvZiBoaWdoUmVhZCBmcm9tIFNlbnNvcnMKI2RlZmluZSBpblNwYWNlICAgICAgNCAgLy9zdGF0ZSBpbmRpY2F0aXZlIG9mIGhpZ2hlc3RSZWFkIGZyb20gU2Vuc29ycwoKLy9SYW5nZSBvZiB2YWx1ZXMgZnJvbSB0aGUgc2Vuc29ycyB0aGF0IGluZGljYXRlIHdoZXJlIHRoZSBsaW5lIGlzLiBUaGVzZQovL25lZWQgdG8gYmUgY2FsaWJyYXRlZCBiYXNlZCBvbiB0aGUgbGluZSBxdWFsaXR5LiAgCi8vVGhlc2UgdHJpZ2dlciBzdGF0ZSBjaGFuZ2VzCi8vb2YgdGhlIHJvdmVyIGFjY29yZGluZyB0byB0aGUgZm9sbG93aW5nIHJhbmdlcy4KLy9vbkxpbmUgPSAwLTgwOyBzcGFjZUluc2lnaHQgPSA4MS0xMjA7IAovL2xpbmVJbnNpZ2h0ID0gMTIxLTE5MDsgaW5TcGFjZSA9IDE5MSsKaW50IGxvd1JlYWQgICAgID0gICAgIDgwOwppbnQgbWlkUmVhZCAgICAgPSAgICAgMTIwOwppbnQgaGlnaFJlYWQgICAgPSAgICAgMTkwOwppbnQgaGlnaGVzdFJlYWQgPSAgICAgMjU1OwoKLy9zZW5zb3JzIHNob3dzIGxvdyB2b2x0YWdlIHdoZW4gbm8gaW5mcmFyZWQgbGlnaHQgaXMgcmVmbGVjdGVkCi8vd2hpY2ggdmFyaWVzIGFjY29yZGluZyB0byB0aGUgcmVmbGVjdGlvbiBkaXN0YW5jZSBhbmQgc3VyZmFjZS4gCi8vVGhlIHZhbHVlIHJlYWQgZnJvbSBBWC0xMSBib2FyZCB3aWxsIHJhbmdlIGZyb20gMTAgdG8gMjU1LiAKLy9MZWZ0IHNlbnNvciBjb25uZWN0ZWQgdG8gQUktMzEgYW5kIFJpZ2h0IGNvbm5lY3RlZCB0byBBSS0xNwojZGVmaW5lIFJFQURfTEVGVCBhbmFsb2coMzEpCiNkZWZpbmUgUkVBRF9NSURETEUgYW5hbG9nKDI1KQojZGVmaW5lIFJFQURfUklHSFQgYW5hbG9nKDE3KQoKLy9BbW91bnQgb2YgdGltZSAoc2Vjb25kcykgZm9yIG1vdG9yIG1vdmVtZW50IHdoZW4gY29tbWFuZGVkIHRvIGRvIHNvCiNkZWZpbmUgRk9SV0FSRF9USU1FICAgMC4xCiNkZWZpbmUgQkFDS1dBUkRfVElNRSAgMC4zCiNkZWZpbmUgSEFSRF9UVVJOX1RJTUUgMC4wNzUKI2RlZmluZSBWRUVSX1RVUk5fVElNRSAwLjAyNQoKdm9pZCBtYWluKCkKeyAgICAKICAgIC8vU3RhdGUgb2YgZWFjaCBzZW5zb3IgKG9uTGluZSwgc3BhY2VJbnNpZ2h0LCBsaW5lSW5zaWdodCwgaW5TcGFjZSkKICAgIGludCBzZW5zb3JbM10gICA9IHswLDAsMH07CiAgICBpbnQgc2Vuc29yUmVhZFszXSA9IHswLDAsMH07IC8vYW5hbG9nIHZhbHVlcyByZWFkIGZyb20gZWFjaCBzZW5zb3IKICAgIGludCBpID0gMDsgLy90ZW1wb3JhcnkgdXNlZCBmb3IgbG9vcHMKICAgIGZsb2F0IGogPSAwLjA7IC8vdXNlZCB3aGVuIGxpbmUgaXMgbm90IGluIHNpZ2h0CiAgICAKICAgIC8vUGF1c2UgZm9yIHRoZSBvcGVyYXRvciB0byBwcmVzcyBzdGFydCBidXR0b24KICAgIHByaW50ZigmcXVvdDtQcmVzcyBTdGFydCFcbiZxdW90Oyk7CiAgICBzdGFydF9wcmVzcygpOwogICAgcHJpbnRmKCZxdW90O0ZvbGxvdyBMaW5lIC4uLlxuJnF1b3Q7KTsKICAgIAogICAgLy9Mb29wIHVudGlsIHRoZSBvcGVyYXRvciBwcmVzc2VzIHRoZSBzdG9wIGJ1dHRvbgogICAgd2hpbGUoIXN0b3BfYnV0dG9uKCkpCiAgICAgIHsKICAgICAgICAvL2NvbnRpbnVvdXNseSByZWFkIGZyb20gdGhlIGxpZ2h0IHNlbnNvcnMuCiAgICAgICAgc2Vuc29yUmVhZFswXSA9IFJFQURfTEVGVDsKICAgICAgICBzZW5zb3JSZWFkWzFdID0gUkVBRF9SSUdIVDsKICAgICAgICBzZW5zb3JSZWFkWzJdID0gUkVBRF9NSURETEU7CiAgICAgICAgCiAgICAgICAgcHJpbnRmKCZxdW90O01ETCA9ICVkXG4mcXVvdDssIHNlbnNvclJlYWRbMl0pOwogICAgICAgIAogICAgICAgIC8vQ2hlY2sgdGhlIHZhbHVlcyBmcm9tIHRoZSBzZW5zb3JzIGFuZCBkZXRlcm1pbmUgdGhlaXIgc3RhdGUKICAgICAgICBmb3IgKGk9MDsgaSZsdDs9MjsgaSsrKQogICAgICAgICAgeyAKICAgICAgICAgICAgaWYgKHNlbnNvclJlYWRbaV0gJmx0Oz0gbG93UmVhZCkKICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzZW5zb3JbaV0gPSBvbkxpbmU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZWxzZSBpZihzZW5zb3JSZWFkW2ldICZsdDs9IG1pZFJlYWQpCiAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc2Vuc29yW2ldID0gc3BhY2VJbnNpZ2h0OwogICAgICAgICAgICB9CiAgICAgICAgICAgIGVsc2UgaWYoc2Vuc29yUmVhZFtpXSAmbHQ7PSBoaWdoUmVhZCkKICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzZW5zb3JbaV0gPSBsaW5lSW5zaWdodDsKICAgICAgICAgICAgfQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgc2Vuc29yW2ldID0gaW5TcGFjZTsKICAgICAgICAgICAgfQogICAgICAgIH0vLyBlbmQgb2YgZm9yIGxvb3AKICAgICAgICAKICAgICAgICAvL0xvZ2ljIHRvIGRldGVybWluZSB3aGF0IG1vdmVzIHRoZSByb3ZlciBzaG91bGQgbWFrZSBuZXh0LgogICAgICAgIGlmKChzZW5zb3JbMl0gPT0gb25MaW5lKSB8fCAoc2Vuc29yUmVhZFsyXSZsdDsxMDApKQogICAgICAgICAgewogICAgICAgICAgICBNb3ZlRm9yd2FyZChGT1JXQVJEX1RJTUUpOwogICAgICAgICAgICBsYXN0TW92ZSA9IDE7CiAgICAgICAgICAgIHdhc0ZvbGxvd2luZ0xpbmUgPSAxOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmKCgoc2Vuc29yWzBdPT1vbkxpbmUpICZhbXA7JmFtcDsgKHNlbnNvclsxXT09b25MaW5lKSkgfHwgKChzZW5zb3JbMF09PWxpbmVJbnNpZ2h0KSAmYW1wOyZhbXA7IChzZW5zb3JbMV09PWxpbmVJbnNpZ2h0KSkgfHwgKChzZW5zb3JbMF09PXNwYWNlSW5zaWdodCkgJmFtcDsmYW1wOyAoc2Vuc29yWzFdPT1zcGFjZUluc2lnaHQpKSkKICAgICAgICAgIHsKLy9Cb3RoIHNlbnNvcnMgZGV0ZWN0IGxpbmUgb3IgbGluZSBpcyBzbWFsbCBpbiB3aWR0aCBhbmQgdGhleSBhcmUgb24gCi8vaXQgb3IgZ2V0dGluZyBuZWFyIGEgbGluZSAtLSZndDsgTW92ZSBGb3J3YXJkCiAgICAgICAgICAgIE1vdmVGb3J3YXJkKEZPUldBUkRfVElNRSk7IC8vY29tbWFuZCByb3ZlciB0byBtb3ZlCiAgICAgICAgICAgIGxhc3RNb3ZlID0gMTsgICAgICAgICAgICAgIC8vc2V0IGRpcmVjdGlvbiBvZiByb3ZlcgogICAgICAgICAgICB3YXNGb2xsb3dpbmdMaW5lID0gMTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZigoKHNlbnNvclswXT09c3BhY2VJbnNpZ2h0KSAmYW1wOyZhbXA7IChzZW5zb3JbMV09PW9uTGluZSkpIHx8ICgoc2Vuc29yWzBdPT1saW5lSW5zaWdodCkgJmFtcDsmYW1wOyAoc2Vuc29yWzFdPT1zcGFjZUluc2lnaHQpKSkKICAgICAgICAgIHsKICAgICAgICAgICAgLy92ZWVyaW5nIG9mZiBjb3Vyc2Ugc28gbW92ZSBhIGxpdHRsZSB0b3dhcmRzIHNlbnNvciBbMV0KICAgICAgICAgICAgTW92ZVJpZ2h0KFZFRVJfVFVSTl9USU1FKTsKICAgICAgICAgICAgbGFzdE1vdmUgPSAzOwogICAgICAgICAgICB3YXNGb2xsb3dpbmdMaW5lID0gMTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZigoKHNlbnNvclswXT09b25MaW5lKSAmYW1wOyZhbXA7IChzZW5zb3JbMV09PXNwYWNlSW5zaWdodCkpIHx8ICgoc2Vuc29yWzBdPT1zcGFjZUluc2lnaHQpICZhbXA7JmFtcDsgKHNlbnNvclsxXT09bGluZUluc2lnaHQpKSkgCiAgICAgICAgICB7CiAgICAgICAgICAgIC8vdmVlcmluZyBvZmYgY291cnNlIHNvIG1vdmUgYSBsaXR0bGUgdG93YXJkcyBzZW5zb3JbMF0KICAgICAgICAgICAgTW92ZUxlZnQoVkVFUl9UVVJOX1RJTUUpOyAgICAgICAgICAgIAogICAgICAgICAgICBsYXN0TW92ZSA9IDI7CiAgICAgICAgICAgIHdhc0ZvbGxvd2luZ0xpbmUgPSAxOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmKCgoc2Vuc29yWzBdPT1vbkxpbmUpJmFtcDsmYW1wOygoc2Vuc29yWzFdPT1saW5lSW5zaWdodCl8fChzZW5zb3JbMV09PWluU3BhY2UpKSkgfHwgKCgoc2Vuc29yWzBdPT1zcGFjZUluc2lnaHQpfHwoc2Vuc29yWzBdPT1saW5lSW5zaWdodCkpJmFtcDsmYW1wOyhzZW5zb3JbMV09PWluU3BhY2UpKSB8fCAoKHNlbnNvclswXT09b25MaW5lKSZhbXA7JmFtcDsoc2Vuc29yWzFdPT1saW5lSW5zaWdodCkpKQogICAgICAgICAgewogICAgICAgICAgICAvL1R1cm4gTGVmdAogICAgICAgICAgICBNb3ZlTGVmdChIQVJEX1RVUk5fVElNRSk7CiAgICAgICAgICAgIGxhc3RNb3ZlID0gMjsKICAgICAgICAgICAgd2FzRm9sbG93aW5nTGluZSA9IDE7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYoKCgoc2Vuc29yWzBdPT1saW5lSW5zaWdodCl8fChzZW5zb3JbMF09PWluU3BhY2UpKSZhbXA7JmFtcDsoc2Vuc29yWzFdPT1vbkxpbmUpKSB8fCAoKHNlbnNvclswXT09aW5TcGFjZSkmYW1wOyZhbXA7KChzZW5zb3JbMV09PXNwYWNlSW5zaWdodCl8fChzZW5zb3JbMV09PWxpbmVJbnNpZ2h0KSkpIHx8ICgoc2Vuc29yWzBdPT1saW5lSW5zaWdodCkmYW1wOyZhbXA7KHNlbnNvclsxXT09b25MaW5lKSkpCiAgICAgICAgICB7CiAgICAgICAgICAgIC8vVHVybiBSaWdodAogICAgICAgICAgICBNb3ZlUmlnaHQoSEFSRF9UVVJOX1RJTUUpOwogICAgICAgICAgICBsYXN0TW92ZSA9IDM7CiAgICAgICAgICAgIHdhc0ZvbGxvd2luZ0xpbmUgPSAxOwogICAgICAgIH0KICAgICAgICBlbHNlIAogICAgICAgICAgewogICAgICAgICAgICAvL05laXRoZXIgc2Vuc29yIGRldGVjdGluZyBhbnl0aGluZyAKICAgICAgICAgICAgaWYod2FzRm9sbG93aW5nTGluZSkKICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBzd2l0Y2ggKGxhc3RNb3ZlKQogICAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICAgICAgICAgICAgeyAgIAovL1RoaXMgc2hvdWxkIG5vdCBvY2N1ciwgdGhpcyBtZWFucyB0aGUgbGFzdCBtb3ZlIHdhcyBub3RoaW5nCi8veWV0IHdhc0ZvbGxvd2luZ0xpbmUgaXMgVFJVRSwgc28gdGhpcyBpcyBhIGZhaWx1cmUgaW4gc29tZXRoaW5nCiAgICAgICAgICAgICAgICAgICAgICAgIHByaW50ZigmcXVvdDtEYW5nZXIsIERhbmdlciFcbiZxdW90Oyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgICAgICAgICAgICB7Ci8vUm92ZXIgd2FzIGZvbGxvd2luZyBsaW5lLCBsb3N0IGl0LCBhbmQgbGFzdCBtb3ZlIHdhcyBmb3J3YXJkCiAgICAgICAgICAgICAgICAgICAgICAgIC8vLS0mZ3Q7IFR1cm4gYXJvdW5kIGFuZCBiYWNrdHJhY2sgdGhlIHdheSB5b3UgY2FtZQogICAgICAgICAgICAgICAgICAgICAgICBNb3ZlQmFja3dhcmQoQkFDS1dBUkRfVElNRSk7CiAgICAgICAgICAgICAgICAgICAgICAgIE1vdmVMZWZ0KEhBUkRfVFVSTl9USU1FKjUuMCk7CiAgICAgICAgICAgICAgICAgICAgICAgIE1vdmVGb3J3YXJkKEZPUldBUkRfVElNRSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHdhc0ZvbGxvd2luZ0xpbmUgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBsYXN0TW92ZSA9IDE7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgICAgICAgICB7Ci8vUm92ZXIgd2FzIGZvbGxvd2luZyBsaW5lLCBsb3N0IGl0LCBhbmQgbGFzdCBtb3ZlIHdhcyBsZWZ0IHR1cm4KICAgICAgICAgICAgICAgICAgICAgICAgLy8tLSZndDsgQmFja3VwIGFuZCB0dXJuIHRvIHRoZSByaWdodAogICAgICAgICAgICAgICAgICAgICAgICBNb3ZlQmFja3dhcmQoQkFDS1dBUkRfVElNRSk7CiAgICAgICAgICAgICAgICAgICAgICAgIE1vdmVSaWdodChIQVJEX1RVUk5fVElNRSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHdhc0ZvbGxvd2luZ0xpbmUgPSAwOwogICAgICAgICAgICAgICAgICAgICAgICBsYXN0TW92ZSA9IDM7CiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0gIAogICAgICAgICAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICAgICAgICAgIHsKLy9Sb3ZlciB3YXMgZm9sbG93aW5nIGxpbmUsIGxvc3QgaXQsIGFuZCBsYXN0IG1vdmUgd2FzIHJpZ2h0IHR1cm4KICAgICAgICAgICAgICAgICAgICAgICAgLy8tLSZndDsgQmFja3VwIGFuZCB0dXJuIHRvIHRoZSBsZWZ0CiAgICAgICAgICAgICAgICAgICAgICAgIE1vdmVCYWNrd2FyZChCQUNLV0FSRF9USU1FKTsKICAgICAgICAgICAgICAgICAgICAgICAgTW92ZUxlZnQoSEFSRF9UVVJOX1RJTUUpOwogICAgICAgICAgICAgICAgICAgICAgICB3YXNGb2xsb3dpbmdMaW5lID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgbGFzdE1vdmUgPSAyOwogICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICB9ICAKICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgICAgICAgewovL1JvdmVyIHdhcyBmb2xsb3dpbmcgbGluZSwgbG9zdCBpdCwgYW5kIGxhc3QgbW92ZSB3YXMgdW5kZWZpbmVkCiAgICAgICAgICAgICAgICAgICAgICAgIC8vLS0mZ3Q7IEJhY2t1cCBhbmQgdHJ5IGFnYWluCiAgICAgICAgICAgICAgICAgICAgICAgIE1vdmVCYWNrd2FyZChCQUNLV0FSRF9USU1FKTsKICAgICAgICAgICAgICAgICAgICAgICAgd2FzRm9sbG93aW5nTGluZSA9IDA7CiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RNb3ZlID0gMDsKICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICAgICAgfSAgCiAgICAgICAgICAgICAgICB9Ly9lbmQgb2Ygc3dpdGNoCiAgICAgICAgICAgIH0vL2VuZCBvZiBpZih3YXNGb2xsb3dpbmdMaW5lKQogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgewovL3dlcmUgbm90IGZvbGxvd2luZyBsaW5lIHNvIHdlIG5lZWQgdG8gbG9jYXRlIGEgbGluZSBzb21ld2hlcmUgaW4gc3BhY2UKICAgICAgICAgICAgICAgIGlmKGxhc3RNb3ZlPT0wKQogICAgICAgICAgICAgICAgICB7Ci8vbm90IGJlZW4gZm9sbG93aW5nIGxpbmUgYW5kIHdlIGhhdmVuJ3QgbW92ZWQgd2UgbXVzdCBiZSBqdXN0IHN0YXJ0aW5nCiAgICAgICAgICAgICAgICAgICAgcHJpbnRmKCZxdW90O2hlcmUgd2UgZ29vb29vb1xuJnF1b3Q7KTsKICAgICAgICAgICAgICAgICAgICBNb3ZlRm9yd2FyZChGT1JXQVJEX1RJTUUpOwogICAgICAgICAgICAgICAgICAgIGxhc3RNb3ZlID0gMTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIC8vbG9vayBmb3IgbGluZSB0YWtpbmcgYSBodW50aW5nIGRvZyBhcHByb2FjaAogICAgICAgICAgICAgICAgICAgIHByaW50ZigmcXVvdDtodW50aW5nIC4uLlxuJnF1b3Q7KTsKICAgICAgICAgICAgICAgICAgICBNb3ZlRm9yd2FyZChGT1JXQVJEX1RJTUUraik7CiAgICAgICAgICAgICAgICAgICAgTW92ZUxlZnQoSEFSRF9UVVJOX1RJTUUpOwovL2luY3JlbWVudGVkIHRvIGluY3JlYXNlIHRoZSBkaWFtZXRlciBvZiB0aGUgY2lyY2xlCiAgICAgICAgICAgICAgICAgICAgaj1qKzAuMDI7ICAKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSAgICAgICAgICAgIAogICAgICAgIH0vL2VuZCBvZiBlbHNlIChuZWl0aGVyIGRldGVjdG9yIGRldGVjdGluZyBhbnl0aGluZwogICAgfS8vZW5kIG9mIHdoaWxlKCFzdG9wX2J1dHRvbikKICAgIAogICAgLy9UdXJuIGFsbCBtb3RvcnMgb2ZmCiAgICBhbygpOwogICAgcHJpbnRmKCZxdW90O0RvbmUgRm9sbG93aW5nIDotKVxuJnF1b3Q7KTsKfS8vZW5kIG9mIHZvaWQgbWFpbigpCgp2b2lkIE1vdmVMZWZ0KGZsb2F0IHgpCnsKICAgIG1vdG9yKDAsLXBjdE1PVE9SX1BPV0VSKTsKICAgIG1vdG9yKDEscGN0TU9UT1JfUE9XRVIpOwogICAgc2xlZXAoeCk7Cn0KCnZvaWQgTW92ZVJpZ2h0KGZsb2F0IHgpCnsKICAgIG1vdG9yKDAscGN0TU9UT1JfUE9XRVIpOwogICAgbW90b3IoMSwtcGN0TU9UT1JfUE9XRVIpOwogICAgc2xlZXAoeCk7ICAgIAp9Cgp2b2lkIE1vdmVGb3J3YXJkKGZsb2F0IHgpCnsKICAgIG1vdG9yKDAscGN0TU9UT1JfUE9XRVIpOwogICAgbW90b3IoMSxwY3RNT1RPUl9QT1dFUik7CiAgICBzbGVlcCh4KTsKfQoKdm9pZCBNb3ZlQmFja3dhcmQoZmxvYXQgeCkKewogICAgbW90b3IoMCwtcGN0TU9UT1JfUE9XRVIpOwogICAgbW90b3IoMSwtcGN0TU9UT1JfUE9XRVIpOwogICAgc2xlZXAoeCk7ICAgICAgIAp9CgoK
1
2Test Code
//////////////////////////////////////////////////////////////////////////////////////////
//File: lineFollow3.ic
//Robust 04/18/2012
//Purpose: Brute force to have rover follow a line (~2.5 inches wide)
//////////////////////////////////////////////////////////////////////////////////////////
int pctMOTOR_POWER = 90; //power level for motors
int wasFollowingLine = 0; //used when off course (not on line)
//direction rover was last going (0=none,1=forward,2=left,3=right)
int lastMove = 0;
//States the rover can be in, as interpreted from the sensor values
#define onLine 1 //state indicative of lowRead from Sensors
#define spaceInsight 2 //state indicative of midRead from Sensors
#define lineInsight 3 //state indicative of highRead from Sensors
#define inSpace 4 //state indicative of highestRead from Sensors
//Range of values from the sensors that indicate where the line is. These
//need to be calibrated based on the line quality.
//These trigger state changes
//of the rover according to the following ranges.
//onLine = 0-80; spaceInsight = 81-120;
//lineInsight = 121-190; inSpace = 191+
int lowRead = 80;
int midRead = 120;
int highRead = 190;
int highestRead = 255;
//sensors shows low voltage when no infrared light is reflected
//which varies according to the reflection distance and surface.
//The value read from AX-11 board will range from 10 to 255.
//Left sensor connected to AI-31 and Right connected to AI-17
#define READ_LEFT analog(31)
#define READ_MIDDLE analog(25)
#define READ_RIGHT analog(17)
//Amount of time (seconds) for motor movement when commanded to do so
#define FORWARD_TIME 0.1
#define BACKWARD_TIME 0.3
#define HARD_TURN_TIME 0.075
#define VEER_TURN_TIME 0.025
void main()
{
//State of each sensor (onLine, spaceInsight, lineInsight, inSpace)
int sensor[3] = {0,0,0};
int sensorRead[3] = {0,0,0}; //analog values read from each sensor
int i = 0; //temporary used for loops
float j = 0.0; //used when line is not in sight
//Pause for the operator to press start button
printf("Press Start!\n");
start_press();
printf("Follow Line ...\n");
//Loop until the operator presses the stop button
while(!stop_button())
{
//continuously read from the light sensors.
sensorRead[0] = READ_LEFT;
sensorRead[1] = READ_RIGHT;
sensorRead[2] = READ_MIDDLE;
printf("MDL = %d\n", sensorRead[2]);
//Check the values from the sensors and determine their state
for (i=0; i<=2; i++)
{
if (sensorRead[i] <= lowRead)
{
sensor[i] = onLine;
}
else if(sensorRead[i] <= midRead)
{
sensor[i] = spaceInsight;
}
else if(sensorRead[i] <= highRead)
{
sensor[i] = lineInsight;
}
else
{
sensor[i] = inSpace;
}
}// end of for loop
//Logic to determine what moves the rover should make next.
if((sensor[2] == onLine) || (sensorRead[2]<100))
{
MoveForward(FORWARD_TIME);
lastMove = 1;
wasFollowingLine = 1;
}
else if(((sensor[0]==onLine) && (sensor[1]==onLine)) || ((sensor[0]==lineInsight) && (sensor[1]==lineInsight)) || ((sensor[0]==spaceInsight) && (sensor[1]==spaceInsight)))
{
//Both sensors detect line or line is small in width and they are on
//it or getting near a line --> Move Forward
MoveForward(FORWARD_TIME); //command rover to move
lastMove = 1; //set direction of rover
wasFollowingLine = 1;
}
else if(((sensor[0]==spaceInsight) && (sensor[1]==onLine)) || ((sensor[0]==lineInsight) && (sensor[1]==spaceInsight)))
{
//veering off course so move a little towards sensor [1]
MoveRight(VEER_TURN_TIME);
lastMove = 3;
wasFollowingLine = 1;
}
else if(((sensor[0]==onLine) && (sensor[1]==spaceInsight)) || ((sensor[0]==spaceInsight) && (sensor[1]==lineInsight)))
{
//veering off course so move a little towards sensor[0]
MoveLeft(VEER_TURN_TIME);
lastMove = 2;
wasFollowingLine = 1;
}
else if(((sensor[0]==onLine)&&((sensor[1]==lineInsight)||(sensor[1]==inSpace))) || (((sensor[0]==spaceInsight)||(sensor[0]==lineInsight))&&(sensor[1]==inSpace)) || ((sensor[0]==onLine)&&(sensor[1]==lineInsight)))
{
//Turn Left
MoveLeft(HARD_TURN_TIME);
lastMove = 2;
wasFollowingLine = 1;
}
else if((((sensor[0]==lineInsight)||(sensor[0]==inSpace))&&(sensor[1]==onLine)) || ((sensor[0]==inSpace)&&((sensor[1]==spaceInsight)||(sensor[1]==lineInsight))) || ((sensor[0]==lineInsight)&&(sensor[1]==onLine)))
{
//Turn Right
MoveRight(HARD_TURN_TIME);
lastMove = 3;
wasFollowingLine = 1;
}
else
{
//Neither sensor detecting anything
if(wasFollowingLine)
{
switch (lastMove)
{
case 0:
{
//This should not occur, this means the last move was nothing
//yet wasFollowingLine is TRUE, so this is a failure in something
printf("Danger, Danger!\n");
break;
}
case 1:
{
//Rover was following line, lost it, and last move was forward
//--> Turn around and backtrack the way you came
MoveBackward(BACKWARD_TIME);
MoveLeft(HARD_TURN_TIME*5.0);
MoveForward(FORWARD_TIME);
wasFollowingLine = 0;
lastMove = 1;
break;
}
case 2:
{
//Rover was following line, lost it, and last move was left turn
//--> Backup and turn to the right
MoveBackward(BACKWARD_TIME);
MoveRight(HARD_TURN_TIME);
wasFollowingLine = 0;
lastMove = 3;
break;
}
case 3:
{
//Rover was following line, lost it, and last move was right turn
//--> Backup and turn to the left
MoveBackward(BACKWARD_TIME);
MoveLeft(HARD_TURN_TIME);
wasFollowingLine = 0;
lastMove = 2;
break;
}
default:
{
//Rover was following line, lost it, and last move was undefined
//--> Backup and try again
MoveBackward(BACKWARD_TIME);
wasFollowingLine = 0;
lastMove = 0;
break;
}
}//end of switch
}//end of if(wasFollowingLine)
else
{
//were not following line so we need to locate a line somewhere in space
if(lastMove==0)
{
//not been following line and we haven't moved we must be just starting
printf("here we goooooo\n");
MoveForward(FORWARD_TIME);
lastMove = 1;
}
else
{
//look for line taking a hunting dog approach
printf("hunting ...\n");
MoveForward(FORWARD_TIME+j);
MoveLeft(HARD_TURN_TIME);
//incremented to increase the diameter of the circle
j=j+0.02;
}
}
}//end of else (neither detector detecting anything
}//end of while(!stop_button)
//Turn all motors off
ao();
printf("Done Following :-)\n");
}//end of void main()
void MoveLeft(float x)
{
motor(0,-pctMOTOR_POWER);
motor(1,pctMOTOR_POWER);
sleep(x);
}
void MoveRight(float x)
{
motor(0,pctMOTOR_POWER);
motor(1,-pctMOTOR_POWER);
sleep(x);
}
void MoveForward(float x)
{
motor(0,pctMOTOR_POWER);
motor(1,pctMOTOR_POWER);
sleep(x);
}
void MoveBackward(float x)
{
motor(0,-pctMOTOR_POWER);
motor(1,-pctMOTOR_POWER);
sleep(x);
}