IyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyDwn46sIE1PVklFIERBVEEgQU5BTFlTSVMgUFJPR1JBTQojIENsYXNzIDEyIENvbXB1dGVyIFNjaWVuY2UgUHJvamVjdCAKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBNYWRlIGJ5OiBCaGF2aWthIEtva2FuZSAmYW1wOyBNYWRpbmEgU2lkaQojIFNjaG9vbDogU3VuZGFyYW0gQ2VudHJhbCBTY2hvb2wKIyBTdWJqZWN0OiBJbmZvcm1hdGljcyBQcmFjdGlzZXMKIyBZZWFyOiAyMDI1LTI2CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgoKcHJpbnQoJnF1b3Q7PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09JnF1b3Q7KQpwcmludCgmcXVvdDsgICAgICDwn5OKIE1PVklFIERBVEEgQU5BTFlTSVMgUFJPR1JBTSDwn5OKJnF1b3Q7KQpwcmludCgmcXVvdDs9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0mcXVvdDspCnByaW50KCZxdW90O0xvYWRpbmcgbW92aWUgZGF0YSBmcm9tIENTViBmaWxlLi4uXG4mcXVvdDspCgppbXBvcnQgcGFuZGFzIGFzIHBkCmltcG9ydCBtYXRwbG90bGliLnB5cGxvdCBhcyBwbHQKCmRmID0gcGQucmVhZF9jc3YoJnF1b3Q7QzpcbXlkYXRhLmNzdiZxdW90OykKcHJpbnQoZGYpCgojIFNob3cgYSBzYW1wbGUgb2YgdGhlIGRhdGEKcHJpbnQoJnF1b3Q7U2FtcGxlIG1vdmllIHJlY29yZHM6JnF1b3Q7KQpwcmludChkZi5oZWFkKCkpCnByaW50KCZxdW90O1xuVG90YWwgbW92aWVzIGxvYWRlZDomcXVvdDssIGxlbihkZikpCnByaW50KCZxdW90Oz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuJnF1b3Q7KQoKCnBsdC5zaG93KCkKIyBoaXN0b2dyYW0gCnBsdC5maWd1cmUoZmlnc2l6ZT0oOCw1KSkKcGx0Lmhpc3QoZGZbJ1JhdGluZyddLCBiaW5zPTEwLCBjb2xvcj0ncHVycGxlJywgZWRnZWNvbG9yPSdibGFjaycpCnBsdC50aXRsZSgnSGlzdG9ncmFtJykKcGx0LnhsYWJlbCgnTnVtZXJpY19jb2x1bW4nKQpwbHQueWxhYmVsKCdGcmVxdWVuY3knKQpwbHQuZ3JpZChUcnVlKQpwbHQuc2hvdygpCgoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFNURVAgMjogTWVudSBMb29wCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQp3aGlsZSBUcnVlOgogICAgcHJpbnQoJnF1b3Q7XG7inKggTU9WSUUgREFUQSBNRU5VIOKcqCZxdW90OykKICAgIHByaW50KCZxdW90Oy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0mcXVvdDspCiAgICBwcmludCgmcXVvdDt8IDEuICBTb3J0IG1vdmllcyBieSByYXRpbmcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8JnF1b3Q7KQogICAgcHJpbnQoJnF1b3Q7fCAyLiAgRmlsdGVyIG1vdmllcyBieSBtaW5pbXVtIHJhdGluZyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCZxdW90OykKICAgIHByaW50KCZxdW90O3wgMy4gIEFkZCBhIG5ldyBtb3ZpZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwmcXVvdDspCiAgICBwcmludCgmcXVvdDt8IDQuICBEZWxldGUgYSBtb3ZpZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8JnF1b3Q7KQogICAgcHJpbnQoJnF1b3Q7fCA1LiAgVXBkYXRlIGEgbW92aWUncyByYXRpbmcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCZxdW90OykKICAgIHByaW50KCZxdW90O3wgNi4gIFNlYXJjaCBmb3IgYSBtb3ZpZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwmcXVvdDspCiAgICBwcmludCgmcXVvdDt8IDcuICBEaXNwbGF5IG1vdmllcyBieSBnZW5yZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8JnF1b3Q7KQogICAgcHJpbnQoJnF1b3Q7fCA4LiAgRGlzcGxheSBtb3ZpZXMgYnkgZGlyZWN0b3IgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCZxdW90OykKICAgIHByaW50KCZxdW90O3wgOS4gIEF2ZXJhZ2UgcmF0aW5nIGJ5IGdlbnJlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwmcXVvdDspCiAgICBwcmludCgmcXVvdDt8IDEwLiBBdmVyYWdlIHJhdGluZyBieSBkaXJlY3RvciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8JnF1b3Q7KQogICAgcHJpbnQoJnF1b3Q7fCAxMS4gQ29tcGFyZSByYXRpbmdzIG9mIHR3byBtb3ZpZXMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCZxdW90OykKICAgIHByaW50KCZxdW90O3wgMTIuIEhpZ2hlc3QgcmF0ZWQgbW92aWUgaW4gYSBnZW5yZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwmcXVvdDspCiAgICBwcmludCgmcXVvdDt8IDEzLiBMb3dlc3QgcmF0ZWQgbW92aWUgaW4gYSBnZW5yZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8JnF1b3Q7KQogICAgcHJpbnQoJnF1b3Q7fCAxNC4gQmFyIENoYXJ0IG9mIFJhdGluZ3MgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCZxdW90OykKICAgIHByaW50KCZxdW90O3wgMTUuIEhpc3RvZ3JhbSBvZiBSYXRpbmdzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwmcXVvdDspCiAgICBwcmludCgmcXVvdDt8IDE2LiBMaW5lIENoYXJ0IG9mIFJhdGluZ3Mgb3ZlciBSZWxlYXNlIERhdGUgICAgICAgICAgICAgICAgICAgICB8JnF1b3Q7KQogICAgcHJpbnQoJnF1b3Q7fCAxNy4gU2hvdyB0b3RhbCBudW1iZXIgb2YgbW92aWVzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCZxdW90OykKICAgIHByaW50KCZxdW90O3wgMTguIFNob3cgdG9wIE4gbW92aWVzIGJ5IHJhdGluZyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwmcXVvdDspCiAgICBwcmludCgmcXVvdDt8IDE5LiBTYXZlIHVwZGF0ZWQgbW92aWUgbGlzdCB0byBDU1YgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8JnF1b3Q7KQogICAgcHJpbnQoJnF1b3Q7fCAyMC4gRXhpdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCZxdW90OykKICAgIHByaW50KCZxdW90Oy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0mcXVvdDspCgogICAgY2hvaWNlID0gaW5wdXQoJnF1b3Q7RW50ZXIgeW91ciBjaG9pY2UgKDEtMjEpOiAmcXVvdDspCgogICAgIyAtLS0tLS0tLS0tLS0tLS0tLS0gT1BUSU9OIDEgLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBpZiBjaG9pY2UgPT0gJnF1b3Q7MSZxdW90OzoKICAgICAgICBwcmludCgmcXVvdDtcbk1vdmllcyBzb3J0ZWQgYnkgcmF0aW5nIChoaWdoZXN0IGZpcnN0KTpcbiZxdW90OykKICAgICAgICBwcmludChkZi5zb3J0X3ZhbHVlcyhieT0mcXVvdDtSYXRpbmcmcXVvdDssIGFzY2VuZGluZz1GYWxzZSkpCgogICAgIyAtLS0tLS0tLS0tLS0tLS0tLS0gT1BUSU9OIDIgLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBlbGlmIGNob2ljZSA9PSAmcXVvdDsyJnF1b3Q7OgogICAgICAgIG1pbl9yYXRpbmcgPSBmbG9hdChpbnB1dCgmcXVvdDtFbnRlciBtaW5pbXVtIHJhdGluZzogJnF1b3Q7KSkKICAgICAgICBmaWx0ZXJlZF9kZiA9IGRmW2RmWyZxdW90O1JhdGluZyZxdW90O10gJmd0Oz0gbWluX3JhdGluZ10KICAgICAgICBwcmludChmJnF1b3Q7XG5Nb3ZpZXMgd2l0aCByYXRpbmcgJmd0Oz0ge21pbl9yYXRpbmd9OlxuJnF1b3Q7KQogICAgICAgIHByaW50KGZpbHRlcmVkX2RmKQoKICAgICMgLS0tLS0tLS0tLS0tLS0tLS0tIE9QVElPTiAzIC0tLS0tLS0tLS0tLS0tLS0tLQogICAgZWxpZiBjaG9pY2UgPT0gJnF1b3Q7MyZxdW90OzoKICAgICAgICB0aXRsZSA9IGlucHV0KCZxdW90O0VudGVyIHRpdGxlOiAmcXVvdDspCiAgICAgICAgZ2VucmUgPSBpbnB1dCgmcXVvdDtFbnRlciBnZW5yZTogJnF1b3Q7KQogICAgICAgIHllYXIgPSBpbnQoaW5wdXQoJnF1b3Q7RW50ZXIgeWVhcjogJnF1b3Q7KSkKICAgICAgICByYXRpbmcgPSBmbG9hdChpbnB1dCgmcXVvdDtFbnRlciByYXRpbmc6ICZxdW90OykpCiAgICAgICAgcmV2ZW51ZSA9IGZsb2F0KGlucHV0KCZxdW90O0VudGVyIHJldmVudWUgKEJpbGxpb24gJCk6ICZxdW90OykpCiAgICAgICAgY291bnRyeSA9IGlucHV0KCZxdW90O0VudGVyIGNvdW50cnk6ICZxdW90OykKICAgICAgICBhY3Rvcl9uYW1lID0gaW5wdXQoJnF1b3Q7RW50ZXIgYWN0b3IgbmFtZTogJnF1b3Q7KQogICAgICAgIGFjdHJlc3NfbmFtZSA9IGlucHV0KCZxdW90O0VudGVyIGFjdHJlc3MgbmFtZTogJnF1b3Q7KQogICAgICAgIGFjdG9yX2xpa2VzID0gaW50KGlucHV0KCZxdW90O0VudGVyIGFjdG9yJ3Mgc29jaWFsIG1lZGlhIGxpa2VzIChNKTogJnF1b3Q7KSkKICAgICAgICBydW50aW1lID0gaW50KGlucHV0KCZxdW90O0VudGVyIHJ1bnRpbWUgKG1pbik6ICZxdW90OykpCiAgICAgICAgZ3Jvc3MgPSBpbnQoaW5wdXQoJnF1b3Q7RW50ZXIgZ3Jvc3MgKCRNKTogJnF1b3Q7KSkKICAgICAgICByZWxlYXNlX2RhdGUgPSBpbnB1dCgmcXVvdDtFbnRlciByZWxlYXNlIGRhdGU6ICZxdW90OykKICAgICAgICBnZW5yZV9jb3VudCA9IGludChpbnB1dCgmcXVvdDtFbnRlciBnZW5yZSBjb3VudDogJnF1b3Q7KSkKICAgICAgICBhdmdfZ2VucmVfcmF0aW5nID0gZmxvYXQoaW5wdXQoJnF1b3Q7RW50ZXIgYXZlcmFnZSBnZW5yZSByYXRpbmc6ICZxdW90OykpCiAgICAgICAgZGlyZWN0b3JfbmFtZSA9IGlucHV0KCZxdW90O0VudGVyIGRpcmVjdG9yIG5hbWU6ICZxdW90OykKICAgICAgICB5ZWFyX3RyZW5kX3Njb3JlID0gaW50KGlucHV0KCZxdW90O0VudGVyIHllYXIgdHJlbmQgc2NvcmU6ICZxdW90OykpCiAgICAgICAgZmFtb3VzX3NvbmcgPSBpbnB1dCgmcXVvdDtFbnRlciBmYW1vdXMgc29uZzogJnF1b3Q7KQoKICAgICAgICAjIEFwcGVuZCB0byBEYXRhRnJhbWUgKHByb3Blcmx5IGluZGVudGVkKQogICAgICAgIGRmLmxvY1tsZW4oZGYpXSA9IFsKICAgICAgICAgICAgdGl0bGUsIGdlbnJlLCB5ZWFyLCByYXRpbmcsIHJldmVudWUsIGNvdW50cnksCiAgICAgICAgICAgIGFjdG9yX25hbWUsIGFjdHJlc3NfbmFtZSwgYWN0b3JfbGlrZXMsIHJ1bnRpbWUsCiAgICAgICAgICAgIGdyb3NzLCByZWxlYXNlX2RhdGUsIGdlbnJlX2NvdW50LCBhdmdfZ2VucmVfcmF0aW5nLAogICAgICAgICAgICBkaXJlY3Rvcl9uYW1lLCB5ZWFyX3RyZW5kX3Njb3JlLCBmYW1vdXNfc29uZwogICAgICAgIF0KICAgICAgICBwcmludCgmcXVvdDvinIUgTW92aWUgYWRkZWQgc3VjY2Vzc2Z1bGx5ISZxdW90OykKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gNCAtLS0tLS0tLS0tLS0tLS0tLS0KICAgIGVsaWYgY2hvaWNlID09ICZxdW90OzQmcXVvdDs6CiAgICAgICAgdGl0bGUgPSBpbnB1dCgmcXVvdDtFbnRlciBleGFjdCBtb3ZpZSB0aXRsZSB0byBkZWxldGU6ICZxdW90OykKICAgICAgICBpZiB0aXRsZSBpbiBkZlsmcXVvdDtUaXRsZSZxdW90O10udmFsdWVzOgogICAgICAgICAgICBkZiA9IGRmW2RmWyZxdW90O1RpdGxlJnF1b3Q7XSAhPSB0aXRsZV0KICAgICAgICAgICAgcHJpbnQoJnF1b3Q74pyFIE1vdmllIGRlbGV0ZWQgc3VjY2Vzc2Z1bGx5ISZxdW90OykKICAgICAgICBlbHNlOgogICAgICAgICAgICBwcmludCgmcXVvdDvinYwgTW92aWUgbm90IGZvdW5kLiZxdW90OykKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gNSAtLS0tLS0tLS0tLS0tLS0tLS0KICAgIGVsaWYgY2hvaWNlID09ICZxdW90OzUmcXVvdDs6CiAgICAgICAgdGl0bGUgPSBpbnB1dCgmcXVvdDtFbnRlciBleGFjdCBtb3ZpZSB0aXRsZSB0byB1cGRhdGU6ICZxdW90OykKICAgICAgICBpZiB0aXRsZSBpbiBkZlsmcXVvdDtUaXRsZSZxdW90O10udmFsdWVzOgogICAgICAgICAgICBuZXdfcmF0aW5nID0gZmxvYXQoaW5wdXQoJnF1b3Q7RW50ZXIgbmV3IHJhdGluZzogJnF1b3Q7KSkKICAgICAgICAgICAgZGYubG9jW2RmWyZxdW90O1RpdGxlJnF1b3Q7XSA9PSB0aXRsZSwgJnF1b3Q7UmF0aW5nJnF1b3Q7XSA9IG5ld19yYXRpbmcKICAgICAgICAgICAgcHJpbnQoJnF1b3Q74pyFIFJhdGluZyB1cGRhdGVkIHN1Y2Nlc3NmdWxseSEmcXVvdDspCiAgICAgICAgZWxzZToKICAgICAgICAgICAgIHByaW50KCZxdW90O+KdjCBNb3ZpZSBub3QgZm91bmQuJnF1b3Q7KQoKICAgICMgLS0tLS0tLS0tLS0tLS0tLS0tIE9QVElPTiA2IC0tLS0tLS0tLS0tLS0tLS0tLQogICAgZWxpZiBjaG9pY2UgPT0gJnF1b3Q7NiZxdW90OzoKICAgICAgICB0aXRsZSA9IGlucHV0KCZxdW90O0VudGVyIG1vdmllIHRpdGxlIHRvIHNlYXJjaDogJnF1b3Q7KQogICAgICAgIHJlc3VsdCA9IGRmW2RmWyZxdW90O1RpdGxlJnF1b3Q7XS5zdHIubG93ZXIoKSA9PSB0aXRsZS5sb3dlcigpXQogICAgICAgIGlmIG5vdCByZXN1bHQuZW1wdHk6CiAgICAgICAgICAgIHByaW50KHJlc3VsdCkKICAgICAgICBlbHNlOgogICAgICAgICAgICBwcmludCgmcXVvdDvinYwgTW92aWUgbm90IGZvdW5kLiZxdW90OykKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gNyAtLS0tLS0tLS0tLS0tLS0tLS0KICAgIGVsaWYgY2hvaWNlID09ICZxdW90OzcmcXVvdDs6CiAgICAgICAgZ2VucmUgPSBpbnB1dCgmcXVvdDtFbnRlciBnZW5yZTogJnF1b3Q7KQogICAgICAgIHJlc3VsdCA9IGRmW2RmWyZxdW90O0dlbnJlJnF1b3Q7XS5zdHIubG93ZXIoKSA9PSBnZW5yZS5sb3dlcigpXQogICAgICAgIGlmIG5vdCByZXN1bHQuZW1wdHk6CiAgICAgICAgICAgIHByaW50KHJlc3VsdCkKICAgICAgICBlbHNlOgogICAgICAgICAgICBwcmludCgmcXVvdDvinYwgTm8gbW92aWVzIGZvdW5kIGZvciB0aGlzIGdlbnJlLiZxdW90OykKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gOCAtLS0tLS0tLS0tLS0tLS0tLS0KICAgIGVsaWYgY2hvaWNlID09ICZxdW90OzgmcXVvdDs6CiAgICAgICAgZGlyZWN0b3IgPSBpbnB1dCgmcXVvdDtFbnRlciBkaXJlY3RvciBuYW1lOiAmcXVvdDspCiAgICAgICAgcmVzdWx0ID0gZGZbZGZbJnF1b3Q7RGlyZWN0b3IgTmFtZSZxdW90O10uc3RyLmxvd2VyKCkgPT0gZGlyZWN0b3IubG93ZXIoKV0KICAgICAgICBpZiBub3QgcmVzdWx0LmVtcHR5OgogICAgICAgICAgICBwcmludChyZXN1bHQpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcHJpbnQoJnF1b3Q74p2MIE5vIG1vdmllcyBmb3VuZCBmb3IgdGhpcyBkaXJlY3Rvci4mcXVvdDspCgogICAgIyAtLS0tLS0tLS0tLS0tLS0tLS0gT1BUSU9OIDkgLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBlbGlmIGNob2ljZSA9PSAmcXVvdDs5JnF1b3Q7OgogICAgICAgIHByaW50KCZxdW90O1xuQXZlcmFnZSByYXRpbmcgYnkgZ2VucmU6JnF1b3Q7KQogICAgICAgIHByaW50KGRmLmdyb3VwYnkoJnF1b3Q7R2VucmUmcXVvdDspWyZxdW90O1JhdGluZyZxdW90O10ubWVhbigpKQoKICAgICMgLS0tLS0tLS0tLS0tLS0tLS0tIE9QVElPTiAxMCAtLS0tLS0tLS0tLS0tLS0tLS0KICAgIGVsaWYgY2hvaWNlID09ICZxdW90OzEwJnF1b3Q7OgogICAgICAgIHByaW50KCZxdW90O1xuQXZlcmFnZSByYXRpbmcgYnkgZGlyZWN0b3I6JnF1b3Q7KQogICAgICAgIHByaW50KGRmLmdyb3VwYnkoJnF1b3Q7RGlyZWN0b3IgTmFtZSZxdW90OylbJnF1b3Q7UmF0aW5nJnF1b3Q7XS5tZWFuKCkpCgogICAgIyAtLS0tLS0tLS0tLS0tLS0tLS0gT1BUSU9OIDExIC0tLS0tLS0tLS0tLS0tLS0tLQogICAgZWxpZiBjaG9pY2UgPT0gJnF1b3Q7MTEmcXVvdDs6CiAgICAgICAgbTEgPSBpbnB1dCgmcXVvdDtFbnRlciBmaXJzdCBtb3ZpZTogJnF1b3Q7KQogICAgICAgIG0yID0gaW5wdXQoJnF1b3Q7RW50ZXIgc2Vjb25kIG1vdmllOiAmcXVvdDspCiAgICAgICAgcjEgPSBkZi5sb2NbZGZbJnF1b3Q7VGl0bGUmcXVvdDtdLnN0ci5sb3dlcigpID09IG0xLmxvd2VyKCksICZxdW90O1JhdGluZyZxdW90O10udmFsdWVzCiAgICAgICAgcjIgPSBkZi5sb2NbZGZbJnF1b3Q7VGl0bGUmcXVvdDtdLnN0ci5sb3dlcigpID09IG0yLmxvd2VyKCksICZxdW90O1JhdGluZyZxdW90O10udmFsdWVzCiAgICAgICAgaWYgcjEuc2l6ZSBhbmQgcjIuc2l6ZToKICAgICAgICAgICAgcHJpbnQoZiZxdW90O3ttMX06IHtyMVswXX0gfCB7bTJ9OiB7cjJbMF19JnF1b3Q7KQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHByaW50KCZxdW90O+KdjCBPbmUgb3IgYm90aCBtb3ZpZXMgbm90IGZvdW5kLiZxdW90OykKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gMTIgLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBlbGlmIGNob2ljZSA9PSAmcXVvdDsxMiZxdW90OzoKICAgICAgICBnZW5yZSA9IGlucHV0KCZxdW90O0VudGVyIGdlbnJlOiAmcXVvdDspCiAgICAgICAgZ19kZiA9IGRmW2RmWyZxdW90O0dlbnJlJnF1b3Q7XS5zdHIubG93ZXIoKSA9PSBnZW5yZS5sb3dlcigpXQogICAgICAgIGlmIG5vdCBnX2RmLmVtcHR5OgogICAgICAgICAgICBwcmludCgmcXVvdDtcbkhpZ2hlc3QgcmF0ZWQgbW92aWUgaW4gdGhpcyBnZW5yZTpcbiZxdW90OykKICAgICAgICAgICAgcHJpbnQoZ19kZi5sb2NbZ19kZlsmcXVvdDtSYXRpbmcmcXVvdDtdLmlkeG1heCgpXSkKICAgICAgICBlbHNlOgogICAgICAgICAgICBwcmludCgmcXVvdDvinYwgTm8gbW92aWVzIGZvdW5kIGluIHRoaXMgZ2VucmUuJnF1b3Q7KQoKICAgICMgLS0tLS0tLS0tLS0tLS0tLS0tIE9QVElPTiAxMyAtLS0tLS0tLS0tLS0tLS0tLS0KICAgIGVsaWYgY2hvaWNlID09ICZxdW90OzEzJnF1b3Q7OgogICAgICAgIGdlbnJlID0gaW5wdXQoJnF1b3Q7RW50ZXIgZ2VucmU6ICZxdW90OykKICAgICAgICBnX2RmID0gZGZbZGZbJnF1b3Q7R2VucmUmcXVvdDtdLnN0ci5sb3dlcigpID09IGdlbnJlLmxvd2VyKCldCiAgICAgICAgaWYgbm90IGdfZGYuZW1wdHk6CiAgICAgICAgICAgIHByaW50KCZxdW90O1xuTG93ZXN0IHJhdGVkIG1vdmllIGluIHRoaXMgZ2VucmU6XG4mcXVvdDspCiAgICAgICAgICAgIHByaW50KGdfZGYubG9jW2dfZGZbJnF1b3Q7UmF0aW5nJnF1b3Q7XS5pZHhtaW4oKV0pCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcHJpbnQoJnF1b3Q74p2MIE5vIG1vdmllcyBmb3VuZCBpbiB0aGlzIGdlbnJlLiZxdW90OykKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gMTQgLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBlbGlmIGNob2ljZSA9PSAmcXVvdDsxNCZxdW90OzoKICAgICAgICBkZl9zb3J0ZWQgPSBkZi5zb3J0X3ZhbHVlcyhieT0mcXVvdDtSYXRpbmcmcXVvdDssIGFzY2VuZGluZz1GYWxzZSkKICAgICAgICBwbHQuZmlndXJlKGZpZ3NpemU9KDEwLCA2KSkKICAgICAgICBwbHQuYmFyKGRmX3NvcnRlZFsmcXVvdDtUaXRsZSZxdW90O10sIGRmX3NvcnRlZFsmcXVvdDtSYXRpbmcmcXVvdDtdLCBjb2xvcj0nc2t5Ymx1ZScpCiAgICAgICAgcGx0Lnh0aWNrcyhyb3RhdGlvbj05MCkKICAgICAgICBwbHQueGxhYmVsKCZxdW90O01vdmllIFRpdGxlJnF1b3Q7KQogICAgICAgIHBsdC55bGFiZWwoJnF1b3Q7UmF0aW5nJnF1b3Q7KQogICAgICAgIHBsdC50aXRsZSgmcXVvdDtNb3ZpZSBSYXRpbmdzIChCYXIgQ2hhcnQpJnF1b3Q7KQogICAgICAgIHBsdC50aWdodF9sYXlvdXQoKQogICAgICAgIHBsdC5zaG93KCkKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gMTUgLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBlbGlmIGNob2ljZSA9PSAmcXVvdDsxNSZxdW90OzoKICAgICAgICBwbHQuZmlndXJlKGZpZ3NpemU9KDgsIDYpKQogICAgICAgIHBsdC5oaXN0KGRmWyZxdW90O1JhdGluZyZxdW90O10sIGJpbnM9MTAsIGNvbG9yPSdsaWdodGdyZWVuJywgZWRnZWNvbG9yPSdibGFjaycpCiAgICAgICAgcGx0LnhsYWJlbCgmcXVvdDtSYXRpbmcmcXVvdDspCiAgICAgICAgcGx0LnlsYWJlbCgmcXVvdDtGcmVxdWVuY3kmcXVvdDspCiAgICAgICAgcGx0LnRpdGxlKCZxdW90O0Rpc3RyaWJ1dGlvbiBvZiBNb3ZpZSBSYXRpbmdzJnF1b3Q7KQogICAgICAgIHBsdC5ncmlkKGF4aXM9J3knKQogICAgICAgIHBsdC5zaG93KCkKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gMTYgLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBlbGlmIGNob2ljZSA9PSAmcXVvdDsxNiZxdW90OzoKICAgICAgICBkZl9zb3J0ZWQgPSBkZi5zb3J0X3ZhbHVlcyhieT0mcXVvdDtSZWxlYXNlIERhdGUmcXVvdDspCiAgICAgICAgcGx0LmZpZ3VyZShmaWdzaXplPSgxMCwgNikpCiAgICAgICAgcGx0LnBsb3QoZGZfc29ydGVkWyZxdW90O1JlbGVhc2UgRGF0ZSZxdW90O10sIGRmX3NvcnRlZFsmcXVvdDtSYXRpbmcmcXVvdDtdLCBtYXJrZXI9J28nLCBjb2xvcj0nb3JhbmdlJykKICAgICAgICBwbHQueHRpY2tzKHJvdGF0aW9uPTQ1KQogICAgICAgIHBsdC54bGFiZWwoJnF1b3Q7UmVsZWFzZSBEYXRlJnF1b3Q7KQogICAgICAgIHBsdC55bGFiZWwoJnF1b3Q7UmF0aW5nJnF1b3Q7KQogICAgICAgIHBsdC50aXRsZSgmcXVvdDtSYXRpbmdzIE92ZXIgVGltZSAoTGluZSBDaGFydCkmcXVvdDspCiAgICAgICAgcGx0LnRpZ2h0X2xheW91dCgpCiAgICAgICAgcGx0LnNob3coKQoKICAgICMgLS0tLS0tLS0tLS0tLS0tLS0tIE9QVElPTiAxNyAtLS0tLS0tLS0tLS0tLS0tLS0KICAgIGVsaWYgY2hvaWNlID09ICZxdW90OzE3JnF1b3Q7OgogICAgICAgIHByaW50KGYmcXVvdDtcblRvdGFsIG51bWJlciBvZiBtb3ZpZXMgaW4gZGF0YWJhc2U6IHtsZW4oZGYpfSZxdW90OykKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gMTggLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBlbGlmIGNob2ljZSA9PSAmcXVvdDsxOCZxdW90OzoKICAgICAgICBuID0gaW50KGlucHV0KCZxdW90O0VudGVyIGhvdyBtYW55IHRvcCBtb3ZpZXMgdG8gZGlzcGxheTogJnF1b3Q7KSkKICAgICAgICBwcmludChkZi5zb3J0X3ZhbHVlcyhieT0mcXVvdDtSYXRpbmcmcXVvdDssIGFzY2VuZGluZz1GYWxzZSkuaGVhZChuKSkKCiAgICAjIC0tLS0tLS0tLS0tLS0tLS0tLSBPUFRJT04gMTkgLS0tLS0tLS0tLS0tLS0tLS0tCiAgICBlbGlmIGNob2ljZSA9PSAmcXVvdDsxOSZxdW90OzoKICAgICAgICBkZi50b19jc3YoJnF1b3Q7dXBkYXRlZF9tb3ZpZXNfX25ldy5jc3YmcXVvdDssIGluZGV4PUZhbHNlKQogICAgICAgIHByaW50KCZxdW90O+KchSBVcGRhdGVkIG1vdmllIGxpc3Qgc2F2ZWQgdG8gJ3VwZGF0ZWRfbW92aWVzLmNzdichJnF1b3Q7KQoKICAgICMgLS0tLS0tLS0tLS0tLS0tLS0tIE9QVElPTiAyMCAtLS0tLS0tLS0tLS0tLS0tLS0KICAgIGVsaWYgY2hvaWNlID09ICZxdW90OzIwJnF1b3Q7OgogICAgICAgIHByaW50KCZxdW90O1xuVGhhbmsgeW91IGZvciB1c2luZyB0aGUgTW92aWUgRGF0YSBBbmFseXNpcyBQcm9ncmFtISDwn46sJnF1b3Q7KQogICAgICAgIGJyZWFrCgogICAgZWxzZToKICAgICAgICBwcmludCgmcXVvdDvinYwgSW52YWxpZCBjaG9pY2UuIFBsZWFzZSB0cnkgYWdhaW4uJnF1b3Q7KQ==
# ------------------------------------------------------------
# š¬ MOVIE DATA ANALYSIS PROGRAM
# Class 12 Computer Science Project
# ------------------------------------------------------------
# Made by: Bhavika Kokane & Madina Sidi
# School: Sundaram Central School
# Subject: Informatics Practises
# Year: 2025-26
# ------------------------------------------------------------
print("======================================================")
print(" š MOVIE DATA ANALYSIS PROGRAM š")
print("======================================================")
print("Loading movie data from CSV file...\n")
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv("C:\mydata.csv")
print(df)
# Show a sample of the data
print("Sample movie records:")
print(df.head())
print("\nTotal movies loaded:", len(df))
print("======================================================\n")
plt.show()
# histogram
plt.figure(figsize=(8,5))
plt.hist(df['Rating'], bins=10, color='purple', edgecolor='black')
plt.title('Histogram')
plt.xlabel('Numeric_column')
plt.ylabel('Frequency')
plt.grid(True)
plt.show()
# -------------------------------
# STEP 2: Menu Loop
# -------------------------------
while True:
print("\n⨠MOVIE DATA MENU āØ")
print("-------------------------------------------------------------------")
print("| 1. Sort movies by rating |")
print("| 2. Filter movies by minimum rating |")
print("| 3. Add a new movie |")
print("| 4. Delete a movie |")
print("| 5. Update a movie's rating |")
print("| 6. Search for a movie |")
print("| 7. Display movies by genre |")
print("| 8. Display movies by director |")
print("| 9. Average rating by genre |")
print("| 10. Average rating by director |")
print("| 11. Compare ratings of two movies |")
print("| 12. Highest rated movie in a genre |")
print("| 13. Lowest rated movie in a genre |")
print("| 14. Bar Chart of Ratings |")
print("| 15. Histogram of Ratings |")
print("| 16. Line Chart of Ratings over Release Date |")
print("| 17. Show total number of movies |")
print("| 18. Show top N movies by rating |")
print("| 19. Save updated movie list to CSV |")
print("| 20. Exit |")
print("-------------------------------------------------------------------")
choice = input("Enter your choice (1-21): ")
# ------------------ OPTION 1 ------------------
if choice == "1":
print("\nMovies sorted by rating (highest first):\n")
print(df.sort_values(by="Rating", ascending=False))
# ------------------ OPTION 2 ------------------
elif choice == "2":
min_rating = float(input("Enter minimum rating: "))
filtered_df = df[df["Rating"] >= min_rating]
print(f"\nMovies with rating >= {min_rating}:\n")
print(filtered_df)
# ------------------ OPTION 3 ------------------
elif choice == "3":
title = input("Enter title: ")
genre = input("Enter genre: ")
year = int(input("Enter year: "))
rating = float(input("Enter rating: "))
revenue = float(input("Enter revenue (Billion $): "))
country = input("Enter country: ")
actor_name = input("Enter actor name: ")
actress_name = input("Enter actress name: ")
actor_likes = int(input("Enter actor's social media likes (M): "))
runtime = int(input("Enter runtime (min): "))
gross = int(input("Enter gross ($M): "))
release_date = input("Enter release date: ")
genre_count = int(input("Enter genre count: "))
avg_genre_rating = float(input("Enter average genre rating: "))
director_name = input("Enter director name: ")
year_trend_score = int(input("Enter year trend score: "))
famous_song = input("Enter famous song: ")
# Append to DataFrame (properly indented)
df.loc[len(df)] = [
title, genre, year, rating, revenue, country,
actor_name, actress_name, actor_likes, runtime,
gross, release_date, genre_count, avg_genre_rating,
director_name, year_trend_score, famous_song
]
print("ā
Movie added successfully!")
# ------------------ OPTION 4 ------------------
elif choice == "4":
title = input("Enter exact movie title to delete: ")
if title in df["Title"].values:
df = df[df["Title"] != title]
print("ā
Movie deleted successfully!")
else:
print("ā Movie not found.")
# ------------------ OPTION 5 ------------------
elif choice == "5":
title = input("Enter exact movie title to update: ")
if title in df["Title"].values:
new_rating = float(input("Enter new rating: "))
df.loc[df["Title"] == title, "Rating"] = new_rating
print("ā
Rating updated successfully!")
else:
print("ā Movie not found.")
# ------------------ OPTION 6 ------------------
elif choice == "6":
title = input("Enter movie title to search: ")
result = df[df["Title"].str.lower() == title.lower()]
if not result.empty:
print(result)
else:
print("ā Movie not found.")
# ------------------ OPTION 7 ------------------
elif choice == "7":
genre = input("Enter genre: ")
result = df[df["Genre"].str.lower() == genre.lower()]
if not result.empty:
print(result)
else:
print("ā No movies found for this genre.")
# ------------------ OPTION 8 ------------------
elif choice == "8":
director = input("Enter director name: ")
result = df[df["Director Name"].str.lower() == director.lower()]
if not result.empty:
print(result)
else:
print("ā No movies found for this director.")
# ------------------ OPTION 9 ------------------
elif choice == "9":
print("\nAverage rating by genre:")
print(df.groupby("Genre")["Rating"].mean())
# ------------------ OPTION 10 ------------------
elif choice == "10":
print("\nAverage rating by director:")
print(df.groupby("Director Name")["Rating"].mean())
# ------------------ OPTION 11 ------------------
elif choice == "11":
m1 = input("Enter first movie: ")
m2 = input("Enter second movie: ")
r1 = df.loc[df["Title"].str.lower() == m1.lower(), "Rating"].values
r2 = df.loc[df["Title"].str.lower() == m2.lower(), "Rating"].values
if r1.size and r2.size:
print(f"{m1}: {r1[0]} | {m2}: {r2[0]}")
else:
print("ā One or both movies not found.")
# ------------------ OPTION 12 ------------------
elif choice == "12":
genre = input("Enter genre: ")
g_df = df[df["Genre"].str.lower() == genre.lower()]
if not g_df.empty:
print("\nHighest rated movie in this genre:\n")
print(g_df.loc[g_df["Rating"].idxmax()])
else:
print("ā No movies found in this genre.")
# ------------------ OPTION 13 ------------------
elif choice == "13":
genre = input("Enter genre: ")
g_df = df[df["Genre"].str.lower() == genre.lower()]
if not g_df.empty:
print("\nLowest rated movie in this genre:\n")
print(g_df.loc[g_df["Rating"].idxmin()])
else:
print("ā No movies found in this genre.")
# ------------------ OPTION 14 ------------------
elif choice == "14":
df_sorted = df.sort_values(by="Rating", ascending=False)
plt.figure(figsize=(10, 6))
plt.bar(df_sorted["Title"], df_sorted["Rating"], color='skyblue')
plt.xticks(rotation=90)
plt.xlabel("Movie Title")
plt.ylabel("Rating")
plt.title("Movie Ratings (Bar Chart)")
plt.tight_layout()
plt.show()
# ------------------ OPTION 15 ------------------
elif choice == "15":
plt.figure(figsize=(8, 6))
plt.hist(df["Rating"], bins=10, color='lightgreen', edgecolor='black')
plt.xlabel("Rating")
plt.ylabel("Frequency")
plt.title("Distribution of Movie Ratings")
plt.grid(axis='y')
plt.show()
# ------------------ OPTION 16 ------------------
elif choice == "16":
df_sorted = df.sort_values(by="Release Date")
plt.figure(figsize=(10, 6))
plt.plot(df_sorted["Release Date"], df_sorted["Rating"], marker='o', color='orange')
plt.xticks(rotation=45)
plt.xlabel("Release Date")
plt.ylabel("Rating")
plt.title("Ratings Over Time (Line Chart)")
plt.tight_layout()
plt.show()
# ------------------ OPTION 17 ------------------
elif choice == "17":
print(f"\nTotal number of movies in database: {len(df)}")
# ------------------ OPTION 18 ------------------
elif choice == "18":
n = int(input("Enter how many top movies to display: "))
print(df.sort_values(by="Rating", ascending=False).head(n))
# ------------------ OPTION 19 ------------------
elif choice == "19":
df.to_csv("updated_movies__new.csv", index=False)
print("ā
Updated movie list saved to 'updated_movies.csv'!")
# ------------------ OPTION 20 ------------------
elif choice == "20":
print("\nThank you for using the Movie Data Analysis Program! š¬")
break
else:
print("ā Invalid choice. Please try again.")