diff --git a/_book/adapter-pattern.md b/_book/adapter-pattern.md new file mode 100644 index 0000000..906932e --- /dev/null +++ b/_book/adapter-pattern.md @@ -0,0 +1,150 @@ +# অ্যাডাপ্টার ডিজাইন প্যাটার্নঃ + +সফটওয়ার ইঞ্জিনিয়ারিং এ আরেকটি বহুল প্রচলিত ডিজাইন প্যাটার্ন হল অ্যাডাপ্টার ডিজাইন প্যাটার্ন। এটি **স্ট্রাকচারাল** প্যাটার্নের মধ্যে পরে। + +আমরা বাস্তব জীবনে সবাই অ্যাডাপ্টার শব্দটির সাথে পরিচিত। +যেমনঃ মোবাইলের চার্জিং অ্যাডাপ্টার, কম্পিউটারের গ্রাফিক্স অ্যাডাপ্টার। + +আর অ্যাডাপ্টার ডিজাইন প্যাটার্ন অনেকটা এই অ্যাডাপ্টারের ন্যায় কাজ করে অর্থাৎ আমরা যদি কম্পিউটারের গ্রাফিক্স কিংবা ভিজিএ অ্যাডাপ্টারের কথা চিন্তা করি তাহলে বলা যায় আমরা গেইম খেলার জন্য এক বিশেষ ধরনের অ্যাডাপ্টার ব্যবহার করি আবার সাধারণ কোন কাজের জন্য সাধারণ অ্যাডাপ্টার হলেই চলে কিন্তু বিষয়বস্তু দুইটারি সমান ভিডিও আউটপুট করা দুইটিই একটা কমন প্যাটার্নে তৈরি। আর মজার বিষয় হল এই অ্যাডাপ্টার গুলো আমাদের খুশি মত আমরা পরিবর্তন করতে পারি। + +এবার ইমপ্লিমেন্টেশনের পরিভাষায়, ধরুন আমরা একটা পিএইচপি প্রজেক্ট কিংবা অ্যাপ্লিকেশন বানাবো যেখানে আমরা ডাটাবেস অ্যাডাপ্টার হিসেবে **MySQL Adapter** আর **PDO Adapter** ব্যাবহার করব যাতে করে ক্লাইন্ট সহজেই তার পছন্দের অ্যাডাপ্টারটি ব্যাবহার করতে পারে **Database** নামে আরেকটি অ্যাডাপ্টারের মাধ্যমে। এতে করে **MySQL Adapter** আর **PDO Adapter** গুলো খুব সহজেই পরিবর্তন করা যাবে। + +নিচে একটা সম্পূর্ণ উদাহরণ দেয়া হলঃ + +```php +connection = new mysqli($host, $username, $password, $dbname); + } + + public function query($sql) + { + $this->result = $this->connection->query($sql); + + return $this; + } + + public function result() + { + if (gettype($this->result) === 'boolean') { + return $this->result; + } elseif ($this->result->num_rows > 0) { + $result = []; + + while ($row = $this->result->fetch_assoc()) { + $result[] = $row; + } + + return $result; + } else { + return []; + } + } +} + +class PDOAdapter implements AdapterInterface +{ + protected $connection; + + protected $result; + + public function __construct($host, $username, $password, $dbname) + { + $this->connection = new PDO("mysql:host=$host;dbname=$dbname", $username, $password); + } + + public function query($sql) + { + $query = $this->connection->prepare($sql); + $exec = $query->execute(); + + if ($query->columnCount() == 0) { + $this->result = $exec; + } else { + $this->result = $query; + } + + return $this; + } + + public function result() + { + if (gettype($this->result) === 'boolean') { + return $this->result; + } else { + $data = []; + + while ($row = $this->result->fetch(PDO::FETCH_ASSOC)) { + $data[] = $row; + } + + return $data; + } + } +} + +class Database +{ + protected $adapter; + + public function __construct(AdapterInterface $adapter) + { + $this->adapter = $adapter; + } + + public function query($sql) + { + return $this->adapter->query($sql); + } + + public function result() + { + return $this->adapter->result(); + } +} + +$mysql = new MySQLAdapter('localhost', 'root', '1234', 'demo'); +$db = new Database($mysql); + +$query = $db->query("SELECT * FROM users"); +$result = $query->result(); +var_dump($result); +``` + + +এখানে ```AdapterInterface``` ইন্টারফেইস ব্যবহার করা হয়েছে যেটিকে ইমপ্লিমেন্ট করে যথাক্রমে ```MySQLAdapter``` ও ```PDOAdapter``` ডিক্লেয়ার করা হয়েছে যাতে দুইটারি ন্যাচার কিংবা কোডবেইস একই থাকে। + +আবার ডাটাবেসকে অ্যাকসেস করার জন্য ও অ্যাডাপ্টারগুলাকে ব্যবহার করার জন্য ```Database``` নামে একটা ক্লাস ডিফাইন করা হয়েছে। +আর এর ডিপেন্ডেন্সি ইনজেকশন হিসেবে ```AdapterInterface``` ব্যবহার করা হয়েছে যাতে করে কেবল মাত্র ```AdapterInterface``` ইমপ্লিমেন্ট করা ক্লাসের ইন্সটান্সই কন্সটারক্টরে পাস করা যায়। + +এখানে আমরা ```MySQLAdapter``` কে ব্যবহার করেছি। + +```php +$mysql = new MySQLAdapter('localhost', 'root', '1234', 'demo'); +$db = new Database($mysql); +``` + +আমরা চাইলে PDOAdapter ও ব্যবহার করতে পারি নিচের মত করে। +```php +$pdo = new PDOAdapter('localhost', 'root', '1234', 'demo'); +$db = new Database($pdo); +``` + +এতে করে অ্যাডাপ্টার গুলা **Loosly Coupled/Highly Decoupled** থাকে আর বর্তমানে এই টার্মটাকে খুবই প্রাধান্য দেয়া হয় বড় কোন অ্যাপ্লিকেশন কিংবা ফ্রেমওয়ার্ক তৈরি করতে গেলে। + +নিচের [লিঙ্ক](https://github.com/sohelamin/php-design-patterns) থেকে সোর্স কোডটি পাবেন। diff --git a/_book/basics.html b/_book/basics.html new file mode 100644 index 0000000..13e843e --- /dev/null +++ b/_book/basics.html @@ -0,0 +1,725 @@ + + + + + + ল্যাঙ্গুয়েজ ব্যাসিকস · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+ +
+ +
+ + + + + + + + +
+
+ +
+
+ +
+ +

ল্যাঙ্গুয়েজ ব্যাসিকস

+

পিএইচপি কিভাবে কাজ করে?

+

পিএইচপি ইনজিন পিএইচপি ফাইল পড়ে লাইন বাই লাইন কোড এক্সিকিউট করে এবং আউটপুট দেয় । পিএইচপি ট্যাগের মধ্যে থাকা সব কোডই এই ইনজিনটি প্রসেস করে । প্রত্যেকটি ইনস্ট্রাকশন এর পর সেমিকোলন ব্যবহার করা হয় । সেমিকোলন দেখে পিএইচপি বুঝে নেয় তার বর্তমান কাজটি কোথায় এসে শেষ হবে ।

+

পিএইচপি ট্যাগ

+

যে কোন পিএইচপি ফাইল শুরুই করতে হয় বিশেষ একটি ট্যাগ ব্যবহার করে । এই ট্যাগটি দেখেই পিএইচপি ইনজিন বুঝতে পারে যে এই জায়গা থেকে পিএইচপি কোড শুরু । তখন সে ঐ ট্যাগের মধ্যবর্তী অংশ লাইন বাই লাইন এক্সিকিউট করে । আবার ট্যাগ শেষ হয়ে গেলে সে ধরে নেয় তার কাজ শেষ, আবার ট্যাগ না আসা পর্যন্ত ফাইলে যা আছে তা ঠিক তেমনভাবেই আউটপুট দিয়ে দেয় ।

+

পিএইচপি ট্যাগ শুরু করতে হয় <?php লিখে আর শেষ হয় ?> লিখে । ফাইলটিতে যদি শুধু পিএইচপি কোডই থাকে তবে ট্যাগ ক্লোজ না করলেও সমস্যা হয় না । তবে যদি আমরা পিএইচপি দিয়ে ডাইনামিক প্রসেসিং এর পাশাপাশি কিছু স্ট্যাটিক অংশও রাখতে চাই সেক্ষেত্রে আমরা পিএইচপি ট্যাগ ওপেন এবং ক্লোজ করে নির্ধারন করে দিতে পারি কোন অংশটুকু ডাইনামিকালি পিএইচপি জেনারেট করবে আর কোন অংশ সবসময়ই একই থাকবে ।

+

যেমন:

+
<p>This is going to be ignored by PHP and displayed by the browser.</p>
+<?php echo 'While this is going to be parsed.'; ?>
+<p>This will also be ignored by PHP and displayed by the browser.</p>
+
+

এখানে আমরা প্রথমে এইচটিএমএল আউটপুট করলাম, এরপর একটা পিএইচপি ব্লক তারপর আবার আগের মতই এইচটিএমএল ।

+

কমেন্টস

+

কমেন্টস হলো কোড এর সেই অংশ যেটা পিএইচপি ইনজিন ইগনোর করে যায় । কমেন্টস এ কোন ইনস্ট্রাকশন থাকে না । মূলত কোড এ কমেন্ট করা হয় ছোট ছোট নোট আকারে । এই নোটগুলো কোড এর বিভিন্ন বিষয় ব্যখ্যা করে । যেমন একটি ভ্যারিয়েবল কি কাজ করে এটা আমরা ঐ ভ্যারিয়েবল এর পাশে কমেন্ট আকারে লিখে দিতে পারি ।

+

পিএইচপিতে ৩ ধরনের কমেন্টস করা সম্ভব:

+
<?php
+
+$name = "masnun"; // সিঙ্গল লাইন কমেন্ট - দুইটা স্ল্যাশ ব্যবহার করা হয় 
+
+/* মাল্টি লাইন কমেন্ট - 
+স্ল্যাশ এর পরে স্টার বা এ্যাস্টেরিস্ক দিয়ে শুরু হয় আবার একইভাবে শেষ হয় - শুধু স্ল্যাশ আর স্টারের সিরিয়াল টা বিপরীত */ 
+
+$age = 75; # একটা হ্যাশ ব্যবহার করে শেল স্টাইলে সিঙ্গল লাইন কমেন্ট করা যায়
+
+

সিঙ্গল লাইন কমেন্ট এর শুরু থেকে লাইনের শেষ পর্যন্ত কমেন্ট হিসেবে বিবেচিত হয় । মাল্টিলাইন কমেন্ট সাধারনত একাধিক লাইন জুড়ে হয় । তবে কমেন্টের শুরু (/*) আর শেষ (*/) এক লাইনেও হওয়া সম্ভব ।

+ + +
+ +
+
+
+ +

results matching ""

+
    + +
    +
    + +

    No results matching ""

    + +
    +
    +
    + +
    +
    + +
    + + + + + + + + + + + + + + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/common-array-functions.html b/_book/common-array-functions.html new file mode 100644 index 0000000..d4e9db3 --- /dev/null +++ b/_book/common-array-functions.html @@ -0,0 +1,832 @@ + + + + + + কমন এ্যারে ফাংশনস · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + + + + + +
    + +
    + +
    + + + + + + + + +
    +
    + +
    +
    + +
    + +

    কমন এ্যারে ফাংশনস

    +

    পিএইচপিতে এ্যারে নিয়ে কাজ করার জন্য প্রচুর ফাংশন রয়েছে । এগুলোর পূর্নাঙ্গ তালিকা পাওয়া যাবে ম্যানুয়ালে - Array Functions সেকশনে । এই চ্যাপ্টারে আমরা বেশি প্রচলিত কিছু এ্যারে সংশ্লিষ্ট ফাংশন সম্পর্কে জানবো । পরবর্তীতে বাকি এ্যারে ফাংশনগুলোও কাভার করা হবে এখানে ।

    +

    এই চ্যাপ্টারটির বেশীরভাগ কন্টেন্ট, বিশেষ করে উদাহরণগুলো পিএইচপি ম্যানুয়াল থেকে নেওয়া । এখানে বাংলায় ব্যখ্যা করা হয়েছে ফাংশনগুলো । নবীনদের জন্য যতটুকু প্রয়োজন ঠিক ততটুকু রাখা হয়েছে । এ্যাডভান্সড কিছু জিনিস ইচ্ছাকৃতভাবেই সংযোজন করা হয়নি ।

    +

    উদাহরণগুলোর আউটপুট ইচ্ছাকৃতভাবেই বইতে দেখানো হয়নি । কোড নিজে থেকে রান করে আউটপুট দেখে বোঝার চেষ্টা করার সুযোগ দেওয়ার জন্যই এমনটি করা হয়েছে ।

    +

    count()

    +

    একটি এ্যারেতে কতগুলি এলিমেন্ট আছে তা জানতে আমরা এই ফাংশনটি ব্যবহার করে থাকি ।

    +
    <?php
    +
    +$array = array(1,2,3);
    +echo count($array);
    +
    +

    এই ফাংশনটি সেকেন্ড প্যারামিটার হিসেবে COUNT_NORMAL কিংবা COUNT_RECURSIVE কন্সট্যান্ট এ্যাক্সেপ্ট করে । এই প্যারামিটারটি অপশনাল । ডিফল্ট ভ্যালু হিসেবে COUNT_NORMAL থাকে । এই মোডে সে শুধু প্রদত্ত এ্যারের কতগুলো আইটেম আছে সেটা হিসেব করে । যখন আমরা COUNT_RECURSIVE ব্যবহার করি তখন এই ফাংশনটি মাল্টি ডাইমেনশনাল এ্যারের ক্ষেত্রে সব গুলো এ্যারের এলিমেন্ট হিসেব করে । অর্থাৎ মূল এ্যারের মধ্যে অন্য কোন এ্যারে থাকলে সেগুলোর এলিমেন্টও গননায় রাখা হবে ।

    +
    <?php
    +$food = array('fruits' => array('orange', 'banana', 'apple'),
    +              'veggie' => array('carrot', 'collard', 'pea'));
    +
    +// রিকার্সিভ মোড
    +echo count($food, COUNT_RECURSIVE); // মোট ৮টি এলিমেন্ট 
    +
    +// নরমাল মোড
    +echo count($food); // ২টি আইটেম
    +
    +

    array_key_exists

    +

    আমাদের এ্যারেতে নির্দিষ্ট নামের কোন কি আছে কিনা তা জানার জন্য আমরা এই ফাংশনটি ব্যবহার করি । ঐ নামের ফাংশন থাকলে আমরা বুলিয়ান true পাই, আর না থাকলে false

    +
    <?php
    +$search_array = array('first' => 1, 'second' => 4);
    +if (array_key_exists('first', $search_array)) {
    +    echo "The 'first' element is in the array";
    +}
    +
    +

    array_keys

    +

    নাম শুনেই বোঝা যাচ্ছে কোন এ্যারে এর কি গুলো পাবো আমরা এই ফাংশন থেকে । এই ফাংশনটির ২য় প্যারামিটার হিসেবে আমরা একটা ওয়ার্ড দিয়ে দিতে পারি, সেক্ষেত্রে শুধুমাত্র যে সকল কি এর মধ্যে ঐ ওয়ার্ডটি থাকবে সেগুলোই রিটার্ন করবে । ৩য় প্যারামিটারটি হচ্ছে === কম্প্যারিজনের জন্য । অর্থাৎ, এটার ভ্যালু ট্রু হলে আগের দেওয়া ওয়ার্ডটি সার্চ করার সময় টাইপ বিবেচনা করা হবে । ২য় এবং ৩য় প্যারামিটার অপশনাল ।

    +

    উদাহরণ:

    +
    <?php
    +$array = array(0 => 100, "color" => "red");
    +print_r(array_keys($array));
    +
    +$array = array("blue", "red", "green", "blue", "blue");
    +print_r(array_keys($array, "blue"));
    +
    +

    array_values

    +

    আগের ফাংশনটির সাথে মিল রেখেই এটি এ্যারের ভ্যালুগুলো রিটার্ন করে । যেমন:

    +
    <?php
    +$array = array("size" => "XL", "color" => "gold");
    +print_r(array_values($array));
    +
    +

    in_array

    +

    এই ফাংশনটি একটি এ্যারেতে একটি নির্দিষ্ট ভ্যালু আছে কিনা তা জানায় । ৩য় প্যারামিটারটি অপশনাল । বুলিয়ান true পাস করলে সার্চ করার সময় টাইপও ম্যাচ করে ।

    +
    <?php
    +$os = array("Mac", "NT", "Irix", "Linux");
    +if (in_array("Irix", $os)) {
    +    echo "Got Irix";
    +}
    +if (in_array("mac", $os)) {
    +    echo "Got mac";
    +}
    +
    +

    array_pop

    +

    এই ফাংশনটি প্রদত্ত এ্যারের শেষ আইটেমটি রিটার্ন করে । এবং একই সাথে ঐ আইটেমটি এ্যারে থেকে রিমুভ করে দেয় ।

    +

    উদাহরণ:

    +
    <?php
    +$stack = array("orange", "banana", "apple", "raspberry");
    +$fruit = array_pop($stack);
    +print_r($stack);
    +
    +

    array_push

    +

    আগের ফাংশনটির ঠিক উল্টো কাজ করে এই ফাংশনটি । এটির কাজ কোন এ্যারের শেষে এক বা একাধিক আইটেম যোগ করা । যেমন:

    +
    <?php
    +$stack = array("orange", "banana");
    +array_push($stack, "apple", "raspberry");
    +print_r($stack);
    +
    +

    এই ফাংশনের প্রথম আর্গুমেন্টটি হবে একটি এ্যারে । এরপর আমরা যে এলিমেন্টগুলো যোগ করতে চাই সেগুলো যোগ করবো ।

    +

    array_shift

    +

    array_pop এ্যারের শেষ থেকে আইটেম বাদ দিতো, array_shift এর কাজ শুরু থেকে বাদ দেওয়া । এটি এ্যারের প্রথম আইটেমটি রিটার্ন করে এবং ঐ আইটেমটি এ্যারেটি থেকে রিমুভ করে দেয় ।

    +

    উদাহরণ:

    +
    <?php
    +$stack = array("orange", "banana", "apple", "raspberry");
    +$fruit = array_shift($stack);
    +print_r($stack);
    +
    +

    array_unshift

    +

    নাম শুনেই বুঝতে পারার কথা এটা কি করে । array_push এর মত করেই এই ফাংশনটি এ্যারের শুরুতে আইটেম যোগ করে । উদাহরণ:

    +
    <?php
    +$queue = array("orange", "banana");
    +array_unshift($queue, "apple", "raspberry");
    +print_r($queue);
    +
    +

    array_flip

    +

    এই ফাংশনটি এ্যারের কি আর ভ্যালু ইন্টারচেইনজ করে দেয় । অর্থাৎ কি গুলো হয়ে যায় ভ্যালু আর ভ্যালুগুলো হয়ে যায় কি । যেমন:

    +
    <?php
    +$trans = array("a" => 1, "b" => 1, "c" => 2);
    +$trans = array_flip($trans);
    +print_r($trans);
    +
    +

    array_reverse

    +

    এই ফাংশনটি এ্যারের আইটেমগুলোর অর্ডার বা ক্রমিক উল্টো করে দেয় । অর্থাৎ প্রথম আইটেমটি শেষে আর শেষের আইটেমটি শুরুতে আসে । এবং অন্যান্য আইটেমগুলিও একইভাবে উল্টো অর্ডারে নিয়ে আসা হয় ।

    +

    আমরা যদি আইটেমের অর্ডার পরিবর্তন হলেও তার আগের কি এর ভ্যালু ঠিক রাখতে চাই তাহলে ২য় আর্গুমেন্টটির ভ্যালু বুলিয়ান true পাস করলেই হবে ।

    +
    <?php
    +$input  = array("php", 4.0, array("green", "red"));
    +$reversed = array_reverse($input);
    +$preserved = array_reverse($input, true);
    +
    +print_r($input);
    +print_r($reversed);
    +print_r($preserved);
    +
    +

    array_merge

    +

    দুই বা ততোধিক এ্যারে মার্জ করে একটি নতুন এ্যারে তৈরি করে এই ফাংশনটি । স্ট্রিং কি এর ক্ষেত্রে যদি একই নামের কি থাকে তবে শেষের এ্যারের একই নামের কি এর ভ্যালু ব্যবহৃত হয় । নিউমেরিক ইনডেক্স এর ক্ষেত্রে আইটেমগুলো একটার পর একটা এ্যাড করে নেয় । কি নিয়ে কোন কনফ্লিক্ট হয় না ।

    +
    <?php
    +$array1 = array("color" => "red", 2, 4);
    +$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
    +$result = array_merge($array1, $array2);
    +print_r($result);
    +
    +

    array_rand

    +

    কোন এ্যারে থেকে এক বা একাধিক র‍‍্যান্ডম আইটেম বেছে নেয় এই ফাংশনটি । ঐ নির্বাচিত আইটেমগুলোর কি রিটার্ন করে । প্রথম প্যারামিটার হিসেবে এ্যারেটি এ্যাক্সেপ্ট করে । ২য় আর্গুমেন্ট হিসেবে আমরা পাস করতে পারি কতগুলো আইটেম বেছে নিবে । ২য় প্যারামিটারটি অপশনাল ।

    +

    যখন একটি মাত্র এন্ট্রি বেছে নেয় তখন এই ফাংশনটি সরাসরি তার কি রিটার্ন করে । তবে একাধিক আইটেম এর বেলায় সে কি গুলো একটি এ্যারেতে রিটার্ন করে ।

    +
    <?php
    +$input = array("Neo", "Morpheus", "Trinity", "Cypher", "Tank");
    +$rand_keys = array_rand($input, 2);
    +echo $input[$rand_keys[0]] . "\n";
    +echo $input[$rand_keys[1]] . "\n";
    +
    +

    array_search

    +

    একটি এ্যারের ভিতরে সার্চ করার জন্য এই ফাংশনটি ব্যবহৃত হয় । যদি এ্যারেতে ওয়ার্ডটি থাকে তবে ঐ আইটেম এর কি টা রিটার্ন করে । যদি ওয়ার্ডটি স্ট্রিং হয় তবে সার্চটি হবে কেইস সেনসিটিভ । অর্থাৎ আপার কেইস ও লোয়ার কেইস এর ভ্যারিয়েশন তখন ম্যাটার করবে । (Masnun আর masnun তখন এক হবে না) । ২য় প্যারামিটারটি অপশনাল । এটি স্ট্রিক্ট (===) কম্প্যারিজন এর জন্য । এটির ভ্যালু বুলিয়ান true পাস করলে সার্চ করার সময় টাইপও মিলিয়ে দেখা হবে ।

    +
    <?php
    +$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
    +
    +$key = array_search('green', $array); // $key = 2;
    +$key = array_search('red', $array);   // $key = 1;
    +
    + + +
    + +
    +
    +
    + +

    results matching ""

    +
      + +
      +
      + +

      No results matching ""

      + +
      +
      +
      + +
      +
      + +
      + + + + + + + + + + + + + + +
      + + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/constants-expressions-operators.html b/_book/constants-expressions-operators.html new file mode 100644 index 0000000..d74570e --- /dev/null +++ b/_book/constants-expressions-operators.html @@ -0,0 +1,800 @@ + + + + + + কন্সট্যান্টস, এক্সপ্রেশনস ও অপারেটরস · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      +
      + + + + + + + + +
      + +
      + +
      + + + + + + + + +
      +
      + +
      +
      + +
      + +

      কন্সট্যান্টস, এক্সপ্রেশনস ও অপারেটরস

      +

      অপরিবর্তনশীল কন্সট্যান্টস

      +

      কন্সট্যান্ট এর নাম শুনেই বোঝা যাচ্ছে এর কাজই হলো পরিবর্তন না হওয়া । কনস্ট্যান্ট হিসেবে আমরা খুব সিম্পল ভ্যালু সংরক্ষণ করতে পারি । define ব্যবহার করে আমরা কন্সট্যান্ট তৈরি করি ।

      +
      <?php
      +define("FOO",     "something");
      +define("FOO2",    "something else");
      +define("FOO_BAR", "something more");
      +
      +

      কন্সট্যান্ট এর নাম সাধারনত বড় হাতের লেখা হয় । নামকরণের ক্ষেত্রে ভ্যারিয়েবলের মতই শুরুতে সংখ্যা ব্যবহার করা যায় না, নামটি কেইস সেনসিটিভ ।

      +

      এক্সপ্রেশনস

      +

      পিএইচপির খুব গুরুত্বেপূর্ণ একটি বিষয় হচ্ছে এক্সপ্রেশন । পিএইচপিতে আমরা মোটামোটি যাই লিখি তার সবই এক্সপ্রেশন । একটি এক্সপ্রেশন এর সবসময়ই একটি ভ্যালু থাকে ।

      +

      আমরা যখন একটি ভ্যারিয়েবল কিংবা কন্সট্যান্ট ডিফাইন করি তখন কিন্তু আমরা একটি এক্সপ্রেশন ব্যবহার করছি । যেমন:

      +
      <?php
      +$name = "masnun";
      +
      +

      এখানে আমরা $name ভ্যারিয়েবল এ masnun স্ট্রিংটি এ্যাসাইন করেছি । এখানে এই "masnun" অংশটুকু হলো একটি এক্সপ্রেশন যার ভ্যালু হলো স্ট্রিং masnun

      +

      আবার যখন এই ভ্যারিয়েবলটিকেই পুনরায় আরেকটি ভ্যারিয়েবল এ এ্যাসাইন করছি তখন:

      +
      <?php
      +
      +$nickname = $name;
      +
      +

      এখানে কিন্তু $name অংশটুকু একটি এক্সপ্রেশন যার ভ্যালু হচ্ছে masnun । এখানে আমরা $nickname এর ভ্যালু হিসেবে $name এক্সপ্রেশনের ভ্যালুকে এ্যাসাইন করেছি ।

      +

      এক্সপ্রেশনের ব্যাসিকটা বুঝে নেওয়া জরুরী কেননা পিএইচপি এক্সপ্রেশন ভিত্তিক ল্যাঙ্গুয়েজ, পিএইচপিতে নানা ধরণের জটিল জটিল এক্সপ্রেশন ব্যবহার করে পরবর্তীতে আমাদের নানা সমস্যার সমাধান করা লাগবে ।

      +

      অপারেটরস

      +

      অপারেটর এক বা একাধিক ভ্যালু কিংবা এক্সপ্রেশনের সম্মিলন ঘটিয়ে একটি নতুন ভ্যালু তৈরি করে । যেমন:

      +
      <?php
      +$a = 23;
      +$b = 5; 
      +
      +$sum = $a + $b + 2;
      +
      +

      এখানে শেষ লাইনে এসে তিনটি ভিন্ন এক্সপ্রেশন এর সমন্বয়ে আমরা নতুন একটি ভ্যালু পাচ্ছি । $a + $b + 2 এটি নিজেও কিন্তু একটি এক্সপ্রেশন । সুতরাং আমরা এভাবেও বলতে পারি, অপারেটরের কাজ হচ্ছে একাধিক এক্সপ্রেশনের সমন্বয়ে নতুন একটি বৃহদাকার এক্সপ্রেশন তৈরি করা ।

      +

      অপারেটর প্রিসিডেন্স

      +

      শুরুতেই আসুন একটি সহজ অঙ্ক করি:

      +
      30 - 4 * 30 / 5 +  4
      +
      +

      বলুনতো এটার ফল কেন 10 হবে? কারণ আমরা জানি এখানে সবার আগে ভাগ এবং গুন এর কাজ করতে হবে এরপর যোগ বিয়োগ । এটাই গনিতের নিয়ম, এখানে এই যে আমরা ভাগ এবং গুনকে অগ্রাধিকার দিলাম, এটাই অপারেটর প্রিসিডেন্স । যখন পিএইচপিতে একাধিক এক্সপ্রেশনের মধ্যে আমরা এমন করে অপারেটর ব্যবহার করি তখন কোন কোন অপারেটর অগ্রাধিকার পায় - তাই সঠিক ফলাফল পেতে আমাদেরকে অপারেটর প্রিসিডেন্স সম্পর্কে বিস্তারিত জানতে হবে ।

      +

      অপারেটর প্রিসিডেন্স সম্পর্কে আরো বিস্তারিত জানতে পিএইচপি ম্যানুয়ালের এই চ্যাপ্টারটি দ্রষ্টব্য - http://php.net/manual/en/language.operators.precedence.php - পরবর্তীতে এই কন্টেন্টও বাংলায় বিশদভাবে ব্যখ্যা করে লেখার ইচ্ছা আছে ।

      +

      কমন অপারেটরস

      +

      গানিতিক অপারেটরগুলো আমরা সবাই কমবেশী চিনি:

      +
      <?php
      +$a = -$a; // মান ঋনাত্বক করা হলো
      +$sum = 2 + 3; // যোগ 
      +$sub = 6 - 3; // বিয়োগ
      +$mul = 5 * 6; // গুন
      +$div = 24 / 3; // ভাগ
      +$mod = 13 % 2; // ১৩ কে ২ দিয়ে ভাগ করলে ভাগশেষ ১
      +$exp = 2 ** 3; // ২ টু দি পাওয়ার ৩ = ৮
      +
      +

      এ্যাসাইনমেন্ট অপারেটর (=) এর সাথে আমরা ইতোমধ্যে পরিচিত হয়েছি, এটার মাধ্যমে আমরা ভ্যালু এ্যাসাইন করি ।

      +
      <?php
      +$a = ($b = 4) + 5;
      +
      +

      এখন $b এর মান 4 এবং $a এর মান হবে 9 । অবজেক্ট টাইপ ব্যতিত প্রায় সকল টাইপের ক্ষেত্রেই এ্যাসাইনমেন্ট অপারেটর ডান পাশের এক্সপ্রেশনের ভ্যালু কপি করে, তাই মূল এক্সপ্রেশনে ব্যবহৃত ভ্যারিয়েবলগুলোর ভ্যালু পরিবর্তন হয় না । তবে আমরা যদি একই চাই যে দুটি ভ্যারিয়েবল ই একই মেমরী ব্লক তথা একই ডাটাকে নির্দেশ করুক সেক্ষেত্রে আমরা একটা & যোগ করে দিতে পারি নিচের মত করে:

      +
      <?php
      +
      +$a = 3;
      +$b = &$a;
      +
      +$a = 5; 
      +echo $b; // এটার মানও পরিবর্তন হয়ে 5 হবে
      +
      +

      এটাকে এ্যসাইনমেন্ট বাই রেফারেন্স বলা হয় ।

      +

      কম্প্যারিজন অপারেটরগুলো দুটো এক্সপ্রেশনের ভ্যালু কম্পেয়ার করার জন্য ব্যবহার করা হয় । যেমন:

      +
      <?php
      +
      +$a == $b; // TRUE হবে যদি $a আর $b এর ভ্যালু টাইপ কনভার্শনের পর একই হয় 
      +$a === $b; // TRUE হবে যদি $a এবং $b এর ভ্যালু একই এবং এরা একই টাইপের হয়
      +$a != $b; // TRUE যদি টাইপ কনভার্শনের পর ভ্যালু একই না হয়
      +$a <> $b; // TRUE যদি টাইপ কনভার্শনের পর ভ্যালু একই না হয়
      +$a !== $b; // TRUE যদি টাইপ কনভার্শনের পর ভ্যালু একই না হয় অথবা তারা একই টাইপ না হয়
      +$a < $b; // TRUE যদি $a, $b থেকে ছোট হয়
      +$a > $b; // TRUE যদি $a, $b থেকে বড় হয়
      +$a <= $b; // TRUE যদি $a, $b এর সমান অথবা $b থেকে ছোট হয়
      +$a >= $b; // TRUE যদি $a, $b এর সমান অথবা $b থেকে বড় হয়
      +
      +

      মনে রাখতে হবে, যদি আমরা স্ট্রিং এর সাথে নাম্বার কম্পেয়ার করি তবে পিএইচপি অটোমেটিক্যালি স্ট্রিংকে নাম্বারে কনভার্ট করবে । এরপর দুই নাম্বার ভ্যালু কম্পেয়ার করবে । তবে === বা !== এর বেলায়, যেখানে টাইপ সহ কম্পেয়ার করা হয় - এসব ক্ষেত্রে টাইপ কনভার্শন অটোমেটিক্যালি হয় না ।

      +

      ইনক্রিমেন্টাল ও ডিক্রিমেন্টাল অপারেটরস:

      +
      <?php
      +++$a // আগে $a এর ভ্যালু এক বাড়িয়ে তারপর $a এর ভ্যালু রিটার্ন করে 
      +$a++ // আগে $a এর ভ্যালু রিটার্ন করে তারপর $a এর ভ্যালু এক বাড়িয়ে দেয় 
      +
      +--$a // ‌আগে $a এর ভ্যালু এক কমিয়ে নেয় তারপর $a এর ভ্যালু রিটার্ন করে 
      +$a-- // আগে $a এর ভ্যালু রিটার্ন করে তারপর $a এর ভ্যালু এক কমিয়ে দেয়
      +
      +

      লজিকাল অপারেটরস:

      +
      <?php
      +$a and $b // TRUE যদি দুটোই TRUE হয়
      +$a or $b // TRUE যদি যে কোন একটা TRUE হয়
      +$a xor $b // TRUE যদি যে কোন একটা TRUE হয় কিন্তু দুটোই TRUE না হয়
      +!$a // TRUE যদি $a TRUE না হয়
      +$a && $b // TRUE যদি দুটোই TRUE হয়
      +$a || $b // TRUE যদি যে কোন একটা TRUE হয়
      +
      +

      নোট: and, or এবং ||, && একই কাজ করলেও এদের অগ্রাধিকার ভিন্ন । যেটা আমরা অপারটের প্রিসিডেন্স টেবিলে বিস্তারিত দেখতে পাবো ।

      +

      এছাড়া আমরা দুটো স্ট্রিং কে সংযুক্ত করতে . অপারেটর ব্যবহার করি । যেমন:

      +
      <?php
      +$a = "Hello ";
      +$b = $a . "World!"; // এখন $b এর ভ্যালু হবে "Hello World!"
      +
      + + +
      + +
      +
      +
      + +

      results matching ""

      +
        + +
        +
        + +

        No results matching ""

        + +
        +
        +
        + +
        +
        + +
        + + + + + + + + + + + + + + +
        + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/control-structures.html b/_book/control-structures.html new file mode 100644 index 0000000..b09efd8 --- /dev/null +++ b/_book/control-structures.html @@ -0,0 +1,853 @@ + + + + + + কন্ট্রোল স্ট্রাকচারস · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        +
        + + + + + + + + +
        + +
        + +
        + + + + + + + + +
        +
        + +
        +
        + +
        + +

        কন্ট্রোল স্ট্রাকচারস

        +

        কন্ট্রোল স্ট্রাকচার - নাম শুনেই আন্দাজ করা যায় কন্ট্রোল রিলেটেড ব্যাপার । একটা পিএইচপি প্রোগ্রামের ফ্লো কন্ট্রোল করাই কন্ট্রোল স্ট্রাকচারের কাজ । আমরা জানি পিএইচপিতে আমাদের কোড লাইন বাই লাইন এক্সিকিউট করা হয় । কখনো কখনো আমাদের এই এক্সিকিউশন কোন শর্তের উপর নির্ভর করে । শর্ত সাপেক্ষে প্রোগ্রাম এর কোন অংশটুকু পিএইচপি এক্সিকিউট করবে সেটা আমরা এই কন্ট্রোল স্ট্রাকচারগুলোর মাধ্যমে নির্ধারণ করে দিবো ।

        +

        কোড ব্লক

        +

        পিএইচপিতে আমরা কয়েকটা স্টেটমেন্টকে একটা গ্রুপ কিংবা ব্লক আকারে ডিফাইন করতে পারি কার্লি ব্রেইস ({ }) ব্যবহার করার মাধ্যমে । ব্লক তৈরি করার সুবিধা হলো যখন কোন শর্ত সাপেক্ষে নির্দিষ্ট কিছু স্টেটমেন্ট রান করতে হয় তখন আমরা ঐ স্টেটমেন্টগুলোকে একটি কোড ব্লকে রেখে পিএইচপি কে বলে দেই অমুক ঘটনা সত্য হলে এই কোড ব্লকের ভিতরে রাখা স্টেটমেন্ট রান করতে । কন্ট্রোল স্ট্রাকচারের সাথে কোড ব্লকের সম্পর্ক গভীর ।

        +

        ইফ, এলস (If, Else)

        +

        কোন একটি বিশেষ শর্ত সাপেক্ষে কোন কোড ব্লক এক্সিকিউট করতে আমরা ইফ, এলস ব্যবহার করি । ইফ এর পরে আমরা একটি এক্সপ্রেশন দেই, এটি যদি সত্য হয় (অর্থাৎ এটার বুলিয়ান ভ্যালু true হয়) তাহলে ইফ ব্লক রান করে । যদি আমরা সাথে একটি এলস ব্লকও দিয়ে দেই, তাহলে ইফ স্টেটমেন্ট false হলে এই বিকল্প ব্লক টি রান করে ।

        +

        উদাহরণ:

        +
        <?php
        +
        +$age = 10; 
        +
        +if($age > 18) {
        +    echo "You are an adult!";
        +} else {
        +    echo "You are not an adult yet!";
        +}
        +
        +

        এখানে আমরা একটি ভ্যারিয়েবল নিয়েছি $age এরপর ইফ ব্লকে আমরা চেক করছি এই ভ্যারিয়েবল এর মান ১৮ অপেক্ষা বেশি কিনা । যদি ১৮ অপেক্ষা বেশি হয় তাহলে প্রথম ব্লক রান করবে । যদি না হয় তবে দ্বিতীয় ব্লক । উপরের কোডটি রান করলে আমরা দেখবো এলস ব্লক রান করেছে কারন এই ভ্যারিয়েবল এর মান আমরা শুরুতেই ১০ নির্ধারণ করে দিয়েছি যেটা নি:সন্দেহে ১৮ থেকে বড় না ।

        +

        আমরা চাইলে একাধিক শর্তও যোগ করতে পারি elseif ব্যবহার করে । এসব ক্ষেত্রে প্রথমে ইফ ব্লক চেক করা হবে, এটা যদি সত্য না হয় তাহলে এলসইফ ব্লকগুলো একটা একটা করে চেক করা হবে । যদি কোনটাই true না হয় তাহলেই এলস ব্লকের কোড রান করবে । যেমন:

        +
        <?php
        +if ($a > $b) {
        +    echo "a is bigger than b";
        +} elseif ($a == $b) {
        +    echo "a is equal to b";
        +} else {
        +    echo "a is smaller than b";
        +}
        +
        +

        পুনশ্চ: একটি ইফ বা এলস কোড ব্লকের মধ্যে চাইলে আরো ইফ এলস ব্লক যোগ করা যায় । এটাকে নেস্টেড ব্লক বলা হয় ।

        +

        হোয়াইল লুপ (While)

        +

        লুপ কি জিনিস তা আমরা সবাই কম বেশি জানি । হোয়াইল লুপের কাজ হচ্ছে আমাদের দিয়ে দেওয়া এক্সপ্রেশন যতক্ষণ পর্যন্ত সত্য হবে ততক্ষন পর্যন্ত সাথে দেওয়া কোড ব্লকটি এক্সিকিউট করা । প্রতিবার লুপ এর শুরুতে ঐ এক্সপ্রেশনটি পিএইচপি চেক করবে, যদি সত্য হয় তাহলে কোড ব্লকটি রান করবে, কোড ব্লক রান করা শেষ হলে সে আবার এক্সপ্রেশনটি চেক করবে - এভাবে চলতেই থাকবে যতক্ষণ পর্যন্ত ঐ এক্সপ্রেশন true রিটার্ন করবে । সুতরাং আমরা বুঝতে পারছি যদি আমাদের লুপ ভেঙ্গে বের হতে হয় তাহলে এমন কোন পরিবর্তন আনতে হবে যাতে ঐ এক্সপ্রেশন এর ভ্যালু আর সত্য না হয় । উদাহরণ দেখে নেই:

        +
        <?php
        +
        +$i = 1;
        +while ($i <= 10) {
        +    echo $i++;  
        +}
        +
        +echo "I am outside the loop";
        +
        +

        এই উদাহরণে দেখুন, আমরা শুরুতে $i এর ভ্যালু দিয়েছি ‍১ । এরপর হোয়াইল লুপে শর্ত দিয়েছি যে $i এর ভ্যালু যতক্ষন ১০ এর ছোট বা সমান হবে ততক্ষণ পর্যন্ত যেন সে কোড ব্লকটি রান করে । লক্ষ্য করুন এই কোড ব্লকের ভিতরে আমরা $i এর ভ্যালু শুধু আউটপুটই দেইনি, সেই সাথে এটার ভ্যালু ১ করে বাড়িয়ে দিয়েছি । প্রতিবার লুপের শুরুতে পিএইচপি চেক করবে ভ্যারিয়েবলটার ভ্যালু ১০ থেকে কম কিনা, এরপর সে ভ্যালুটা আউটপুট দিয়ে সাথে ১ যোগ করে দিবে । এভাবে লুপ চলতে চলতে একটা সময় এসে $i এর ভ্যালু বাড়তে বাড়তে ১০ এর বেশি হয়ে যাবে । তখন আর হোয়াইল লুপে দেওয়া শর্ত সত্য থাকবে না, পিএইচপি তখন লুপ থেকে বের হয়ে পরবর্তী কোড এক্সিকিউট করা শুরু করবে ।

        +

        ডু-হোয়াইল লুপ (do-while)

        +

        আমরা দেখেছি হোয়াইল লুপ প্রথমেই শর্তটি চেক করে । যদি সত্য হয় তবেই সে কোড ব্লক রান করে । যদি এমন হয় যে প্রথমবারেই শর্তটি মিথ্যা হলো, তখন? তখন আর কোড ব্লকটি একবারো রান করবে না । ডু-হোয়াইল লুপের ব্যাপারটা একটু ভিন্ন । এখানে আমরা প্রথমে কোড ব্লক দিয়ে দেই, পিএইচপি এটা রান করে আগে, এরপর হোয়াইল লুপের কন্ডিশন টা চেক করে । যদি সত্য হয় তাহলে আবার কোড ব্লক রান করে, সত্য না হলে লুপ ভেঙ্গে বের হয়ে যায় ।

        +

        যেহেতু ডু-হোয়াইল লুপে কোড ব্লক প্রথমে রান করে এবং এক্সপ্রেশন এর ভ্যালু পরে চেক করা হয় তাই নিশ্চিতভাবে বলা যায় যে প্রদত্ত কোড ব্লকটি অন্তত একবার রান করবেই । ঠিক এই একবার রান করা নিশ্চিত করার জন্যই হোয়াইল এর পরিবর্তে ডু-হোয়াইল ব্যবহার করা হয় ।

        +

        কোড এক্সাম্পল দেখে নেই:

        +
        <?php
        +$i = 0;
        +do {
        +    echo $i;
        +} while ($i > 0);
        +
        +

        দেখুন এখানে $i এর ভ্যালু ০ অপেক্ষা বেশি না হলেও কোড ব্লকটি রান করে এবং ০ আউটপুট দেয় ।

        +

        ফর লুপ (for)

        +

        এটা একটু তুলনামূলকভাবে জটিল লুপ । এখানে আমরা ৩টা এক্সপ্রেশন দিয়ে দেই -

        +
          +
        • প্রথমটা যখন প্রথমবার লুপ শুরু হবে তখন রান করা হবে ।
        • +
        • ২য় টা হচ্ছে লুপের মূল শর্ত, হোয়াইল লুপের মত প্রতিবার লুপ শুরু হওয়ার সময় এটা চেক করা হবে । এটার বুলিয়ান ভ্যালু true হলেই কেবল লুপটি চলবে ।
        • +
        • ৩য়টা প্রতিবার কোড ব্লক শেষ করে রান করা হয় ।
        • +
        +

        আমরা খুব সিম্পল একটা উদাহরণ দেখে নেই:

        +
        <?php
        +for ($i = 1; $i <= 10; $i++) {
        +    echo $i;
        +}
        +
        +

        এখানে,

        +
          +
        • $i = 1 এটা লুপ প্রথমবার শুরু হওয়ার সময়ই রান করবে । অর্থাৎ আমরা $i এর ভ্যালু ১ সেট করে নিলাম ।
        • +
        • এবার হলো শর্ত পরীক্ষা করার পালা । প্রতিবার লুপের শুরুতে চেক করা হবে $i এর ভ্যালু ১০ এর সমান কিংবা কম আছে কিনা । থাকলে কোড রান করবে, না হলে লুপ শেষ করে বের হয়ে যাবে ।
        • +
        • প্রতিবার লুপ শেষে আমরা ভ্যারিয়েবলটির ভ্যালু ১ করে বাড়িয়ে দিচ্ছি যাতে একটা সময় গিয়ে এটার ভ্যালু ১০ এর বেশি হয় ।
        • +
        +

        সংক্ষেপে এটাই হলো ফর লুপের কাহিনী । আমরা চাইলে যে কোন এক্সপ্রেশন ফাকা রাখতে পারি । যদি আমরা ভুলে বা ইচ্ছাকৃতভাবে ২য় এক্সপ্রেশনটি ফাকা রাখি, সেক্ষেত্রে ফর লুপটি চলতেই থাকবে কেননা এটি কতক্ষন পর্যন্ত চলতে হবে সেই নির্দেশনটা আমরা পিএইচপি কে দেই নি ।

        +

        ফর-ইচ লুপ (foreach)

        +

        কোন এ্যারে থেকে ভ্যালুগুলোকে একটা একটা নিয়ে কাজ করার জন্যই ফর-ইচ লুপ ব্যবহার করা হয় । এই লুপের এক্সপ্রেশন হিসেবে আমরা বলে দেই একটি এ্যারে থেকে কিভাবে প্রতিটা আইটেম নিতে হবে । এরপর সেই নির্দেশনা অনুযায়ী পিএইচপি আইটেমগুলোকে একটা একটা করে আমাদের কোড ব্লকে পাস করে । প্রতি লুপে এভাবে আমরা এ্যারের একেকটি আইটেম পাই । যতক্ষণ পর্যন্ত ঐ এ্যারের সবগুলো আইটেম একবার করে নেওয়া না হবে ততক্ষণ পর্যন্ত এই লুপ চলতেই থাকবে ।

        +

        আমরা আমাদের এক্সপ্রেশন এ বলে দিতে পারি যে আমরা কি শুধু এ্যারের ভ্যালুটা চাই নাকি ইনডেক্স ভ্যালু দুটোই চাই । নিচের উদাহরণ দেখি:

        +
        <?php
        +
        +// এই উদাহরণে শুধুই আইটেম টি নিবো
        +$arr = array(1, 2, 3, 4);
        +foreach ($arr as $value) {
        +    echo $value;
        +}
        +
        +// এখানে আমরা ইনডেক্স এবং ভ্যালু দুটোই নিবো
        +$arr2 = array("a" => "abdullah", "b" => "bahar");
        +foreach($arr2 as $k => $v) {
        +    echo $k. "=". $v;
        +}
        +
        +

        প্রথম উদাহরণে আমরা পিএইচপিকে বলে দিচ্ছি $arr এ্যারে থেকে একেকটি আইটেম নিয়ে সেটিকে $value ভ্যারিয়েবলে রাখতে । এরপর কোড ব্লকটি রান করতে । ২য় উদাহরণে, আমরা বলে দিচ্ছি ইনডেক্স এর ভ্যালু টা $k এবং আইটেম এর ভ্যালুটা $v ভ্যারিয়েবলে রেখে কোড ব্লকটি রান করাতে ।

        +

        সুইচ (switch)

        +

        সুইচ ব্যবহার করে আমরা খুব সহজে কোন একটা এক্সপ্রেশন এর ভ্যালুর উপর নির্ভর করে অনেকগুলো সিদ্ধান্ত থেকে এক বা একাধিক বেছে নিতে পারি । এর আগে আমরা ইফ-এলস, এলস-ইফ এর ব্যবহার দেখেছি । যখন অনেকগুলো শর্ত পরপর চেক করার প্রয়োজন হয় তখন আমরা এলস-ইফ ব্যবহার করি, অনেকটা নিচের মত করে -

        +
        <?php
        +if ($i == 0) {
        +    echo "i equals 0";
        +} elseif ($i == 1) {
        +    echo "i equals 1";
        +} elseif ($i == 2) {
        +    echo "i equals 2";
        +}
        +
        +

        সাধারনত এরকমভাবে একগাদা এলস-ইফ ব্লক এ্যভয়েড করার জন্য সুইচ পারফেক্ট । এখানে আমরা কয়েকটা কন্ডিশন চেক করছি, প্রথমে দেখছি $i এর ভ্যালু শুন্য কিনা, এরপর চেক করছি এটির মান ১ কিনা, এরপর আবার দেখছি ২ কিনা । সুইচ এর মাধ্যমে এভাবে বার বার চেক না করে, একবারেই চেক করে মান অনুসারে সিদ্ধান্ত নেওয়া যায় । উপরের কোডই আমরা সুইচ ব্যবহার করে এভাবে লিখতে পারি -

        +
        <?php
        +switch ($i) {
        +    case 0:
        +        echo "i equals 0";
        +        break;
        +    case 1:
        +        echo "i equals 1";
        +        break;
        +    case 2:
        +        echo "i equals 2";
        +        break;
        +}
        +
        +

        এখানে, আমরা $i এর ভ্যালুর উপর নির্ভর করে আমাদের সিদ্ধান্ত নিবো তাই এটাকে সুইচ এ পাস করা হয়েছে । এরপর আমাদের কোড ব্লকের ভিতরে কতগুলো case বা সম্ভাব্য ঘটনা বিচার করা হয়েছে । case এর সাথে আমরা প্রত্যাশিত ভ্যালু দিয়ে একেকটি কেইস ডিফাইন করি । যেমন, case 0 মানে হলো $i এর মান যখন 0 হবে তখন এই কেইসটি সত্য । এরপর কোলন (:) দিয়ে আমরা আমাদের প্রয়োজনীয় কোড লিখি । এখানে আমরা একটা আউটপুট দিয়ে রেখেছি । এরপর যে কোন কেইস মিলে গেলে আমরা চাই সুইচ ব্লক থেকে বের হয়ে যেতে, তাই break এর ব্যবহার । break সম্পর্কে আমরা একটু পরেই জানবো । আপাতত জেনে রাখি, কোন কেইস এর পর ব্রেক না থাকলে ঐ কেইসটি ম্যাচ করেই পিএইচপি থেমে যাবে না, বরং পরবর্তী কেইসগুলাও ম্যাচ করে দেখবে । একাধিক কেইসও এভাবে ম্যাচ করা সম্ভব । তবে অধিকাংশ ক্ষেত্রেই আমরা চাইবো একটি কেইস ম্যাচ করলে সুইচ থেকে বের হয়ে যেতে ।

        +

        ব্রেক (break)

        +

        যে কোন ধরণের কন্ট্রোল স্ট্রাকচার থেকে বের হয়ে আসতে ব্রেক ব্যবহার করা হয় । যেমন:

        +
        <?php
        +$array = ["a", "b", "c", "d"];
        +foreach($array as $val) {
        +    echo $val;
        +    if($val == "b") {
        +        break;
        +    }
        +}
        +
        +

        এই উদাহরণে আমরা দেখছি, এ্যারে থেকে সবগুলো আইটেম নেওয়ার আগেই লুপটি বন্ধ হয়ে যাচ্ছে, কারণ যখনই আইটেম এর ভ্যালু b হচ্ছে তখনই আমরা break স্টেটমেন্ট ব্যবহার করে লুপ থেকে বের হয়ে আসছি । ফলে বাকি আইটেমগুলো আর আউটপুটে আসছে না ।

        +

        কন্টিনিউ (continue)

        +

        ব্রেক এর কাজ লুপ থেকে বের হয়ে যাওয়া, কন্টিনিউ এর কাজ বর্তমান লুপের বাকি অংশ স্কিপ করে সরাসরি পরবর্তী লুপ শুরু করা ।

        +
        <?php
        +for ($i = 0; $i < 5; ++$i) {
        +    if ($i == 2) {
        +        continue; 
        +    }
        +    print "$i\n";
        +}
        +
        +

        এই কোডটি রান করলে 2 আউটপুটে আসবে না, কারণ যখনই $i এর ভ্যালু ২ হবে তখনই পিএইচপি কন্টিনিউ স্টেটমেন্টটি দেখবে । তখন আর কোড ব্লকের বাকি অংশ রান না করেই পরবর্তী লুপে প্রবেশ করবে । তাই print "$i\n"; এই অংশটি ২ এর বেলায় এক্সিকিউট করা হবে না, আউটপুটেও তাই ২ আসবে না । অর্থাৎ লুপিং এর সময় কন্টিনিউ ব্যবহার করলে পিএইচপি সাথে সাথে ব্লকের বাকি অংশ স্কিপ করে পরবর্তী আইটেমে চলে যায় ।

        +

        এক্সারসাইজ

        +
          +
        1. একটা স্ক্রিপ্ট লিখেন যেটা চলতি মাসের নাম নিবে এবং তার উপর ভিত্তি করে নিচের মেসেজ প্রিন্ট করবে।
            +
          • যদি মাসের নাম November হয় তাহলে প্রিন্ট করবে, Winter is comming.
          • +
          +
        2. +
        3. যদি November না হয়, তাহলে প্রিন্ট করবে, You better stay in South.

          +

          হিন্টস : date('F', time()) এইটা ব্যবহার করে অাপনি, মাসের নাম নিতে পারবেন।

          +
        4. +
        +

        2.ধরুন অাপনি Zimbabwe এর একজন বাসিন্দা । অাপনার বন্ধু বিভিন্ন দেশে ঘুরে ঘুরে খেলা দেখে । সে অাপনাকে একদিন বলল, " ওমুক দেশটা খুব সুন্দর "। বন্ধুর কথা শুনে, অাপনার ঐদেশে ঘুরতে যেতে ইচ্ছে হল। কিন্তু সে অাপনাকে দেশেটির নাম বলেনি। বরং অাপনাকে একটি চিরকুট দিল। যাতে লেখা - "Bangladesh is beautiful country" । এবং সে অাপনাকে কতগুলো দেশের নামের লিস্ট দিল যেগুলো হল -"England", "Bangladesh", "Sri Lanka", "India" ।

        +

        এখন এই দুটো তথ্যের উপর ভিত্তি করে অাপনাকে ঐদেশের নাম কি সেটা বলতে হবে।

        +

        হিন্টস : স্ট্রিং কে অ্যারেতে কনভার্ট করার জন্য explode() ফাংশনটি ব্যবহার করতে পারেন। ডিটেইলস : http://php.net/manual/en/function.explode.php

        +

        অামরা পরবর্তিতে অারোও এক্সারসাইজ দেয়ার চেষ্টা করব।

        + + +
        + +
        +
        +
        + +

        results matching ""

        +
          + +
          +
          + +

          No results matching ""

          + +
          +
          +
          + +
          +
          + +
          + + + + + + + + + + + + + + +
          + + +
          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/decorator-pattern.md b/_book/decorator-pattern.md new file mode 100644 index 0000000..3705e1f --- /dev/null +++ b/_book/decorator-pattern.md @@ -0,0 +1,67 @@ +# ডেকোরেটর ডিজাইন প্যাটার্নঃ + +`Decorator` ডিজাইন প্যাটার্ন স্ট্রাকচারাল ডিজাইন প্যাটার্নের মধ্যে পরে। +`Decorator` শব্দটি শুনলেই আমরা বুঝতে পারছি যে এটি কোন কিছুর প্রসাধক হিসেবে কাজ করে থাকে। + +অবজেক্ট ওরিয়েন্টেডের ক্ষেত্রে ডেকোরেটর একটি নির্দিষ্ট অবজেক্টকে স্টাটিক্যালি অথবা ডায়নামিক্যালি সংযুক্তি বা পরিবর্তন করে থাকে। + +এখন প্রশ্ন আসতে পারে আমরা কোন ক্লাসকে ইনহেরিট করেই তো এই কাজটি করতে পারি তাহলে কেন ডেকোরেটর ব্যাবহার করবো? +ইনহেরিট্যান্স এর মাধ্যমে আমরা একটা ক্লাসকে পরিবর্তন করে থাকি তার মানে সাবক্লাস দিয়ে আমরা যতগুলো অবজেক্ট তৈরি করবো সবগুলাই সেইম হবে। অন্যদিকে ডেকোরেটর আমাদেরকে এই ক্ষেত্রে শুধুমাত্র কোন নির্দিষ্ট অবজেক্টে পরিবর্তন করতে ফ্লেক্সিবিলিটি দিয়ে থাকে। + +এবার চলুন একটা উদাহরণ দেখা যাক। + +```php + +interface EmailInterface +{ + public function body(); +} + +class Email implements EmailInterface +{ + public function body() + { + return 'Simple email body.'; + } +} + +abstract class EmailDecorator implements EmailInterface +{ + public $email; + + public function __construct(EmailInterface $email) + { + $this->email = $email; + } + + abstract public function body(); +} + +class NewYearEmailDecorator extends EmailDecorator +{ + public function body() + { + return $this->email->body() . ' Additional text from deocorator.'; + } +} +``` + +উপরের কোডে খেয়াল করলে দেখতে পাবেন ইমেইল পাঠানোর জন্য একটি মুল ইন্টারফেইস `EmailInterface` আর এর কনক্রিট ক্লাস `Email` ইমপ্লিমেন্ট করা হয়েছে যা দিয়ে আমরা সিম্পল ইমেইল করতে পারি। + +এবার ডেকোরেটর এর জন্য `EmailDecorator` অ্যাবস্ট্রাক্ট ক্লাস ডিফাইন করেছি আর এইটা কে ইনহেরিট করে `NewYearEmailDecorator` কনক্রিট ক্লাস ডিফাইন করেছি যার মাধ্যমে আমরা খুব সহজেই ইমেইলের অবজেক্টকে পরিবর্তন/সংযুক্তি করতে পারবো। + +আমরা চাইলে `EmailDecorator` অ্যাবস্ট্রাক্ট ক্লাসটি ইনহেরিট করে আরও ক্লাস ডিফাইন করতে পারি। + +এবার নিচের কোডটি দেখলে বুঝতে পারবেন কিভাবে অবজেক্টকে ডেকোরেট করা হয়েছে। + +```php +// Simple Email +$email = new Email(); +var_dump($email->body()); + +// Decorated Email +$emailNewYearDecorator = new NewYearEmailDecorator($email); +var_dump($emailNewYearDecorator->body()); +``` + +এই চ্যাপ্টারের সোর্স কোডটি [এই লিঙ্ক](https://github.com/sohelamin/php-design-patterns) থেকে পাবেন। diff --git a/_book/dependency-injection-pattern.md b/_book/dependency-injection-pattern.md new file mode 100644 index 0000000..eff6675 --- /dev/null +++ b/_book/dependency-injection-pattern.md @@ -0,0 +1,95 @@ +# ডিপেন্ডেন্সি ইনজেকশন ডিজাইন প্যাটার্নঃ + +ডিপেন্ডেন্সি ইনজেকশন স্ট্রাকচারাল ডিজাইন প্যাটার্নের মধ্যে পরে। এইটা এমন একটা ডিজাইন প্যাটার্ন যা কোন ক্লাসের ডিপেন্ডেন্সি অর্থাৎ প্রয়োজনীয় অবজেক্ট গুলোকে রান টাইম কিংবা কম্পাইল টাইমে সহজে পরিবর্তনে সহায়তা করে। + +এই প্যাটার্নের মূল উদ্দেশ্যই হল লুজলি কাপল আর্কিটেকচার ইমপ্লিমেন্ট করা যাতে করে একটা ভাল মানের অ্যাপ তৈরি করা যায়। + +ডিপেন্ডেন্সি ইনজেকশন ডিজাইন প্যাটার্ন হল ```S.O.L.I.D Principle``` এর ```D``` যার পূর্ণ অর্থ ```Dependency Inversion Principle (DIP)``` যেটি ```Inversion of Control (IoC)``` কে অনুসরণ করে। + +এখানে ```Dependency Inversion Principle``` বলতে ```Decoupling``` করাকে বুঝানো হয় আর ```Inversion of Control``` বলতে কিভাবে ডিপেন্ডেন্সি রিজল্ভ করা হবে সেটিকে বুঝায়। ডিপেন্ডেন্সি রিজল্ভ করতে ```Dependency Injection (DI) Container``` বা ```Inversion of Control (IoC) Container``` ব্যাবহৃত হয়ে থাকে। + +আমরা সাধারণত একটি ক্লাসে অন্য ক্লাসের অবজেক্ট ব্যাবহার করলে নিচের মত করে হার্ডকোড করি যা হাইলি কাপল্ড থাকে। + +```php +class Database +{ + protected $adapter; + + public function __construct() + { + $this->adapter = new MySqlAdapter; + } +} + +class MysqlAdapter +{ + +} +``` + +আর ডিপেন্ডেন্সি ইনজেকশন ডিজাইন প্যাটার্নে কোন ক্লাস কিংবা ইন্টারফেইসকে টাইপ হিন্ট করে কনস্ট্রাক্টর কিংবা মেথডে ইঞ্জেক্ট করতে হয় নিচের মত করে। + +```php +class Database +{ + protected $adapter; + + public function __construct(MySqlAdapter $adapter) + { + $this->adapter = $adapter; + } +} + +class MysqlAdapter +{ + +} +``` + +উপরে ```MySqlAdapter``` ক্লাসকে ডিপেন্ডেন্সি হিসেবে রাখা হয়েছে। আর এই ডিপেন্ডেন্সি রিজল্ভ করতে হলে অবশ্যই ```MySqlAdapter``` এর অবজেক্ট কন্সট্রাক্টরের প্যারামিটারে দিতে হবে। + +যেমনঃ +```php +$mysqlAdapter = new MysqlAdapter; +$database = new Database($mysqlAdapter); +``` + +ডিপেন্ডেন্সি প্রধানত তিন ভাবে ইনজেক্ট করা যায়। + +## ১. কন্সট্রাক্টর ইনজেকশনঃ +যা কনস্ট্রাক্টরের মাধ্যমে ইঞ্জেক্ট করা হয়। + +```php +public function __construct(MySqlAdapter $adapter) +{ + $this->adapter = $adapter; +} +``` + +## ২. সেটার ইনজেকশনঃ +যা কোন মেথডের প্যারামিটারে ইঞ্জেক্ট করা হয়। + +```php +public function setterMethod(MySqlAdapter $adapter) +{ + $this->adapter = $adapter; +} +``` + +## ৩. ইন্টারফেইস ইনজেকশনঃ +ইন্টারফেইসকে কোন কনস্ট্রাক্টরে অথবা সেটার মেথডে ইঞ্জেক্ট করা হয়। + +```php +public function __construct(AdapterInterface $adapter) +{ + $this->adapter = $adapter; +} +``` + +আমরা আমাদের প্রজেক্টে ডিপেন্ডেন্সি গুলোকে স্বয়ংক্রিয় ভাবে ইঞ্জেক্ট কিংবা রিজল্ভ করতে ডিপেন্ডেন্সি ইনজেকশন কন্টেইনার ব্যাবহার করব যা আগেই উল্লেখ করেছি। +অনেক ফ্রেমওয়ার্কে এই কন্টেইনার সাধারণত বিল্ট-ইন দেয়া থাকে যেমনঃ ```Symfony```, ```Laravel```, ```Yii``` + +আমরা সাধারণ প্রজেক্টের ক্ষেত্রে ```Pimple``` নামে কন্টেইনারটি ব্যাবহার করতে পারি। +আবার আমি আমার কাজের জন্য খুব সহজ এবং অপ্টিমাইজ একটা কন্টেইনার বানিয়েছিলাম আপনারা চাইলে সেটি দেখতে পারেন [এই লিঙ্ক](https://github.com/appzcoder/container) থেকে। আশাকরি সোর্স কোড ও ডকুমেন্টেশন থেকে আপনারা ভাল ধারণা পাবেন। + +এই চ্যাপ্টারের সোর্স কোডটি [এই লিঙ্ক](https://github.com/sohelamin/php-design-patterns) থেকে পাবেন। \ No newline at end of file diff --git a/_book/design-patterns.md b/_book/design-patterns.md new file mode 100644 index 0000000..323af91 --- /dev/null +++ b/_book/design-patterns.md @@ -0,0 +1,24 @@ +# ডিজাইন প্যাটার্ন + +সফটওয়্যার ইঞ্জিনিয়ারিং এ ডিজাইন প্যাটার্ন হল কোডের সাধারণ সমস্যার রি-ইউজিবিলিটি বাড়ানোর জন্য এক প্রকারের নিয়মনীতি অথবা টেম্পলেট। যাতে করে সফটওয়্যার একটা নির্দিষ্ট আর্কিটেকচার এ তৈরি করা যায় আর কোডের পুনুরাব্রিত্তি ঠেকান যায়। + +ডিজাইন প্যাটার্ন সাধারণত নিম্মলিখিত ক্যাটাগরীর হয়ে থাকেঃ + +1. Creational +2. Structural +3. Behavioural + +আমরা বহুল ব্যাবহ্রিত গুলো নিয়ে আলোচনা করব। + +### টপিকস লিস্ট + +* [সিঙ্গেলটোন](singleton-pattern.md) +* [অবজার্ভার](observer-pattern.md) +* [অ্যাডাপ্টার](adapter-pattern.md) +* [ফ্যাক্টরী](factory-pattern.md) +* [ডিপেন্ডেন্সি ইনজেকশন](dependency-injection-pattern.md) +* [ফ্যাসাড](facade-pattern.md) +* [স্ট্রাটেজি](strategy-pattern.md) +* [ইটারেটর](iterator-pattern.md) +* [প্রক্সি](proxy-pattern.md) +* [ডেকোরেটর](decorator-pattern.md) diff --git a/_book/design-patterns/adapter-pattern.html b/_book/design-patterns/adapter-pattern.html new file mode 100644 index 0000000..306bac4 --- /dev/null +++ b/_book/design-patterns/adapter-pattern.html @@ -0,0 +1,831 @@ + + + + + + অ্যাডাপ্টার · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
          +
          + + + + + + + + +
          + +
          + +
          + + + + + + + + +
          +
          + +
          +
          + +
          + +

          অ্যাডাপ্টার

          +

          সফটওয়ার ইঞ্জিনিয়ারিং এ আরেকটি বহুল প্রচলিত ডিজাইন প্যাটার্ন হল অ্যাডাপ্টার ডিজাইন প্যাটার্ন। এটি স্ট্রাকচারাল প্যাটার্নের মধ্যে পরে।

          +

          আমরা বাস্তব জীবনে সবাই অ্যাডাপ্টার শব্দটির সাথে পরিচিত। যেমনঃ মোবাইলের চার্জিং অ্যাডাপ্টার, কম্পিউটারের গ্রাফিক্স অ্যাডাপ্টার।

          +

          আর অ্যাডাপ্টার ডিজাইন প্যাটার্ন অনেকটা এই অ্যাডাপ্টারের ন্যায় কাজ করে অর্থাৎ আমরা যদি কম্পিউটারের গ্রাফিক্স কিংবা ভিজিএ অ্যাডাপ্টারের কথা চিন্তা করি তাহলে বলা যায় আমরা গেইম খেলার জন্য এক বিশেষ ধরনের অ্যাডাপ্টার ব্যবহার করি আবার সাধারণ কোন কাজের জন্য সাধারণ অ্যাডাপ্টার হলেই চলে কিন্তু বিষয়বস্তু দুইটারি সমান ভিডিও আউটপুট করা দুইটিই একটা কমন প্যাটার্নে তৈরি। আর মজার বিষয় হল এই অ্যাডাপ্টার গুলো আমাদের খুশি মত আমরা পরিবর্তন করতে পারি।

          +

          এবার ইমপ্লিমেন্টেশনের পরিভাষায়, ধরুন আমরা একটা পিএইচপি প্রজেক্ট কিংবা অ্যাপ্লিকেশন বানাবো যেখানে আমরা ডাটাবেস অ্যাডাপ্টার হিসেবে MySQL Adapter আর PDO Adapter ব্যাবহার করব যাতে করে ক্লাইন্ট সহজেই তার পছন্দের অ্যাডাপ্টারটি ব্যাবহার করতে পারে Database নামে আরেকটি অ্যাডাপ্টারের মাধ্যমে। এতে করে MySQL Adapter আর PDO Adapter গুলো খুব সহজেই পরিবর্তন করা যাবে।

          +

          নিচে একটা সম্পূর্ণ উদাহরণ দেয়া হলঃ

          +
          <?php
          +
          +interface AdapterInterface
          +{
          +    public function query($sql);
          +
          +    public function result();
          +}
          +
          +class MySQLAdapter implements AdapterInterface
          +{
          +    protected $connection;
          +
          +    protected $result;
          +
          +    public function __construct($host, $username, $password, $dbname)
          +    {
          +        $this->connection = new mysqli($host, $username, $password, $dbname);
          +    }
          +
          +    public function query($sql)
          +    {
          +        $this->result = $this->connection->query($sql);
          +
          +        return $this;
          +    }
          +
          +    public function result()
          +    {
          +        if (gettype($this->result) === 'boolean') {
          +            return $this->result;
          +        } elseif ($this->result->num_rows > 0) {
          +            $result = [];
          +
          +            while ($row = $this->result->fetch_assoc()) {
          +                $result[] = $row;
          +            }
          +
          +            return $result;
          +        } else {
          +            return [];
          +        }
          +    }
          +}
          +
          +class PDOAdapter implements AdapterInterface
          +{
          +    protected $connection;
          +
          +    protected $result;
          +
          +    public function __construct($host, $username, $password, $dbname)
          +    {
          +        $this->connection = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
          +    }
          +
          +    public function query($sql)
          +    {
          +        $query = $this->connection->prepare($sql);
          +        $exec = $query->execute();
          +
          +        if ($query->columnCount() == 0) {
          +            $this->result = $exec;
          +        } else {
          +            $this->result = $query;
          +        }
          +
          +        return $this;
          +    }
          +
          +    public function result()
          +    {
          +        if (gettype($this->result) === 'boolean') {
          +            return $this->result;
          +        } else {
          +            $data = [];
          +
          +            while ($row = $this->result->fetch(PDO::FETCH_ASSOC)) {
          +                $data[] = $row;
          +            }
          +
          +            return $data;
          +        }
          +    }
          +}
          +
          +class Database
          +{
          +    protected $adapter;
          +
          +    public function __construct(AdapterInterface $adapter)
          +    {
          +        $this->adapter = $adapter;
          +    }
          +
          +    public function query($sql)
          +    {
          +        return $this->adapter->query($sql);
          +    }
          +
          +    public function result()
          +    {
          +        return $this->adapter->result();
          +    }
          +}
          +
          +$mysql = new MySQLAdapter('localhost', 'root', '1234', 'demo');
          +$db = new Database($mysql);
          +
          +$query = $db->query("SELECT * FROM users");
          +$result = $query->result();
          +var_dump($result);
          +
          +

          এখানে AdapterInterface ইন্টারফেইস ব্যবহার করা হয়েছে যেটিকে ইমপ্লিমেন্ট করে যথাক্রমে MySQLAdapterPDOAdapter ডিক্লেয়ার করা হয়েছে যাতে দুইটারি ন্যাচার কিংবা কোডবেইস একই থাকে।

          +

          আবার ডাটাবেসকে অ্যাকসেস করার জন্য ও অ্যাডাপ্টারগুলাকে ব্যবহার করার জন্য Database নামে একটা ক্লাস ডিফাইন করা হয়েছে। আর এর ডিপেন্ডেন্সি ইনজেকশন হিসেবে AdapterInterface ব্যবহার করা হয়েছে যাতে করে কেবল মাত্র AdapterInterface ইমপ্লিমেন্ট করা ক্লাসের ইন্সটান্সই কন্সটারক্টরে পাস করা যায়।

          +

          এখানে আমরা MySQLAdapter কে ব্যবহার করেছি।

          +
          $mysql = new MySQLAdapter('localhost', 'root', '1234', 'demo');
          +$db = new Database($mysql);
          +
          +

          আমরা চাইলে PDOAdapter ও ব্যবহার করতে পারি নিচের মত করে।

          +
          $pdo = new PDOAdapter('localhost', 'root', '1234', 'demo');
          +$db = new Database($pdo);
          +
          +

          এতে করে অ্যাডাপ্টার গুলা Loosly Coupled/Highly Decoupled থাকে আর বর্তমানে এই টার্মটাকে খুবই প্রাধান্য দেয়া হয় বড় কোন অ্যাপ্লিকেশন কিংবা ফ্রেমওয়ার্ক তৈরি করতে গেলে।

          +

          নিচের লিঙ্ক থেকে সোর্স কোডটি পাবেন।

          + + +
          + +
          +
          +
          + +

          results matching ""

          +
            + +
            +
            + +

            No results matching ""

            + +
            +
            +
            + +
            +
            + +
            + + + + + + + + + + + + + + +
            + + +
            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/decorator-pattern.html b/_book/design-patterns/decorator-pattern.html new file mode 100644 index 0000000..56b7725 --- /dev/null +++ b/_book/design-patterns/decorator-pattern.html @@ -0,0 +1,745 @@ + + + + + + ডেকোরেটর · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            +
            + + + + + + + + +
            + +
            + +
            + + + + + + + + +
            +
            + +
            +
            + +
            + +

            ডেকোরেটর

            +

            Decorator ডিজাইন প্যাটার্ন স্ট্রাকচারাল ডিজাইন প্যাটার্নের মধ্যে পরে। Decorator শব্দটি শুনলেই আমরা বুঝতে পারছি যে এটি কোন কিছুর প্রসাধক হিসেবে কাজ করে থাকে।

            +

            অবজেক্ট ওরিয়েন্টেডের ক্ষেত্রে ডেকোরেটর একটি নির্দিষ্ট অবজেক্টকে স্টাটিক্যালি অথবা ডায়নামিক্যালি সংযুক্তি বা পরিবর্তন করে থাকে।

            +

            এখন প্রশ্ন আসতে পারে আমরা কোন ক্লাসকে ইনহেরিট করেই তো এই কাজটি করতে পারি তাহলে কেন ডেকোরেটর ব্যাবহার করবো? ইনহেরিট্যান্স এর মাধ্যমে আমরা একটা ক্লাসকে পরিবর্তন করে থাকি তার মানে সাবক্লাস দিয়ে আমরা যতগুলো অবজেক্ট তৈরি করবো সবগুলাই সেইম হবে। অন্যদিকে ডেকোরেটর আমাদেরকে এই ক্ষেত্রে শুধুমাত্র কোন নির্দিষ্ট অবজেক্টে পরিবর্তন করতে ফ্লেক্সিবিলিটি দিয়ে থাকে।

            +

            এবার চলুন একটা উদাহরণ দেখা যাক।

            +
            interface EmailInterface
            +{
            +    public function body();
            +}
            +
            +class Email implements EmailInterface
            +{
            +    public function body()
            +    {
            +        return 'Simple email body.';
            +    }
            +}
            +
            +abstract class EmailDecorator implements EmailInterface
            +{
            +    public $email;
            +
            +    public function __construct(EmailInterface $email)
            +    {
            +        $this->email = $email;
            +    }
            +
            +    abstract public function body();
            +}
            +
            +class NewYearEmailDecorator extends EmailDecorator
            +{
            +    public function body()
            +    {
            +        return $this->email->body() . ' Additional text from deocorator.';
            +    }
            +}
            +
            +

            উপরের কোডে খেয়াল করলে দেখতে পাবেন ইমেইল পাঠানোর জন্য একটি মুল ইন্টারফেইস EmailInterface আর এর কনক্রিট ক্লাস Email ইমপ্লিমেন্ট করা হয়েছে যা দিয়ে আমরা সিম্পল ইমেইল করতে পারি।

            +

            এবার ডেকোরেটর এর জন্য EmailDecorator অ্যাবস্ট্রাক্ট ক্লাস ডিফাইন করেছি আর এইটা কে ইনহেরিট করে NewYearEmailDecorator কনক্রিট ক্লাস ডিফাইন করেছি যার মাধ্যমে আমরা খুব সহজেই ইমেইলের অবজেক্টকে পরিবর্তন/সংযুক্তি করতে পারবো।

            +

            আমরা চাইলে EmailDecorator অ্যাবস্ট্রাক্ট ক্লাসটি ইনহেরিট করে আরও ক্লাস ডিফাইন করতে পারি।

            +

            এবার নিচের কোডটি দেখলে বুঝতে পারবেন কিভাবে অবজেক্টকে ডেকোরেট করা হয়েছে।

            +
            // Simple Email
            +$email = new Email();
            +var_dump($email->body());
            +
            +// Decorated Email
            +$emailNewYearDecorator = new NewYearEmailDecorator($email);
            +var_dump($emailNewYearDecorator->body());
            +
            +

            এই চ্যাপ্টারের সোর্স কোডটি এই লিঙ্ক থেকে পাবেন।

            + + +
            + +
            +
            +
            + +

            results matching ""

            +
              + +
              +
              + +

              No results matching ""

              + +
              +
              +
              + +
              +
              + +
              + + + + + + + + + + +
              + + +
              + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/dependency-injection-pattern.html b/_book/design-patterns/dependency-injection-pattern.html new file mode 100644 index 0000000..9ba05a4 --- /dev/null +++ b/_book/design-patterns/dependency-injection-pattern.html @@ -0,0 +1,767 @@ + + + + + + ডিপেন্ডেন্সি ইনজেকশন · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
              +
              + + + + + + + + +
              + +
              + +
              + + + + + + + + +
              +
              + +
              +
              + +
              + +

              ডিপেন্ডেন্সি ইনজেকশন

              +

              ডিপেন্ডেন্সি ইনজেকশন স্ট্রাকচারাল ডিজাইন প্যাটার্নের মধ্যে পরে। এইটা এমন একটা ডিজাইন প্যাটার্ন যা কোন ক্লাসের ডিপেন্ডেন্সি অর্থাৎ প্রয়োজনীয় অবজেক্ট গুলোকে রান টাইম কিংবা কম্পাইল টাইমে সহজে পরিবর্তনে সহায়তা করে।

              +

              এই প্যাটার্নের মূল উদ্দেশ্যই হল লুজলি কাপল আর্কিটেকচার ইমপ্লিমেন্ট করা যাতে করে একটা ভাল মানের অ্যাপ তৈরি করা যায়।

              +

              ডিপেন্ডেন্সি ইনজেকশন ডিজাইন প্যাটার্ন হল S.O.L.I.D Principle এর D যার পূর্ণ অর্থ Dependency Inversion Principle (DIP) যেটি Inversion of Control (IoC) কে অনুসরণ করে।

              +

              এখানে Dependency Inversion Principle বলতে Decoupling করাকে বুঝানো হয় আর Inversion of Control বলতে কিভাবে ডিপেন্ডেন্সি রিজল্ভ করা হবে সেটিকে বুঝায়। ডিপেন্ডেন্সি রিজল্ভ করতে Dependency Injection (DI) Container বা Inversion of Control (IoC) Container ব্যাবহৃত হয়ে থাকে।

              +

              আমরা সাধারণত একটি ক্লাসে অন্য ক্লাসের অবজেক্ট ব্যাবহার করলে নিচের মত করে হার্ডকোড করি যা হাইলি কাপল্ড থাকে।

              +
              class Database
              +{
              +    protected $adapter;
              +
              +    public function __construct()
              +    {
              +        $this->adapter = new MySqlAdapter;
              +    }
              +}
              +
              +class MysqlAdapter
              +{
              +
              +}
              +
              +

              আর ডিপেন্ডেন্সি ইনজেকশন ডিজাইন প্যাটার্নে কোন ক্লাস কিংবা ইন্টারফেইসকে টাইপ হিন্ট করে কনস্ট্রাক্টর কিংবা মেথডে ইঞ্জেক্ট করতে হয় নিচের মত করে।

              +
              class Database
              +{
              +    protected $adapter;
              +
              +    public function __construct(MySqlAdapter $adapter)
              +    {
              +        $this->adapter = $adapter;
              +    }
              +}
              +
              +class MysqlAdapter
              +{
              +
              +}
              +
              +

              উপরে MySqlAdapter ক্লাসকে ডিপেন্ডেন্সি হিসেবে রাখা হয়েছে। আর এই ডিপেন্ডেন্সি রিজল্ভ করতে হলে অবশ্যই MySqlAdapter এর অবজেক্ট কন্সট্রাক্টরের প্যারামিটারে দিতে হবে।

              +

              যেমনঃ

              +
              $mysqlAdapter = new MysqlAdapter;
              +$database = new Database($mysqlAdapter);
              +
              +

              ডিপেন্ডেন্সি প্রধানত তিন ভাবে ইনজেক্ট করা যায়।

              +

              ১. কন্সট্রাক্টর ইনজেকশনঃ

              +

              যা কনস্ট্রাক্টরের মাধ্যমে ইঞ্জেক্ট করা হয়।

              +
              public function __construct(MySqlAdapter $adapter)
              +{
              +    $this->adapter = $adapter;
              +}
              +
              +

              ২. সেটার ইনজেকশনঃ

              +

              যা কোন মেথডের প্যারামিটারে ইঞ্জেক্ট করা হয়।

              +
              public function setterMethod(MySqlAdapter $adapter)
              +{
              +    $this->adapter = $adapter;
              +}
              +
              +

              ৩. ইন্টারফেইস ইনজেকশনঃ

              +

              ইন্টারফেইসকে কোন কনস্ট্রাক্টরে অথবা সেটার মেথডে ইঞ্জেক্ট করা হয়।

              +
              public function __construct(AdapterInterface $adapter)
              +{
              +    $this->adapter = $adapter;
              +}
              +
              +

              আমরা আমাদের প্রজেক্টে ডিপেন্ডেন্সি গুলোকে স্বয়ংক্রিয় ভাবে ইঞ্জেক্ট কিংবা রিজল্ভ করতে ডিপেন্ডেন্সি ইনজেকশন কন্টেইনার ব্যাবহার করব যা আগেই উল্লেখ করেছি। অনেক ফ্রেমওয়ার্কে এই কন্টেইনার সাধারণত বিল্ট-ইন দেয়া থাকে যেমনঃ Symfony, Laravel, Yii

              +

              আমরা সাধারণ প্রজেক্টের ক্ষেত্রে Pimple নামে কন্টেইনারটি ব্যাবহার করতে পারি। আবার আমি আমার কাজের জন্য খুব সহজ এবং অপ্টিমাইজ একটা কন্টেইনার বানিয়েছিলাম আপনারা চাইলে সেটি দেখতে পারেন এই লিঙ্ক থেকে। আশাকরি সোর্স কোড ও ডকুমেন্টেশন থেকে আপনারা ভাল ধারণা পাবেন।

              +

              এই চ্যাপ্টারের সোর্স কোডটি এই লিঙ্ক থেকে পাবেন।

              + + +
              + +
              +
              +
              + +

              results matching ""

              +
                + +
                +
                + +

                No results matching ""

                + +
                +
                +
                + +
                +
                + +
                + + + + + + + + + + + + + + +
                + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/facade-pattern.html b/_book/design-patterns/facade-pattern.html new file mode 100644 index 0000000..d915d36 --- /dev/null +++ b/_book/design-patterns/facade-pattern.html @@ -0,0 +1,855 @@ + + + + + + ফ্যাসাড · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                +
                + + + + + + + + +
                + +
                + +
                + + + + + + + + +
                +
                + +
                +
                + +
                + +

                ফ্যাসাড

                +

                Facade ডিজাইন প্যাটার্ন স্ট্রাকচারাল ডিজাইন প্যাটার্নের মধ্যে পরে। ফ্যাসাড ডিজাইন প্যাটার্ন এর কাজ হল ক্লায়েন্ট এর কাছে একটা কমপ্লেক্স সিস্টেম বা ইন্টারফেইস হতে একটা সহজ ইন্টারফেইস প্রদান করা যাতে কমপ্লেক্স কিংবা আগলি কোড গুলো হিডেন অবস্থায় থাকে।

                +

                লেগাসি কিংবা কমপ্লেক্স কোন সিস্টেম এর কোডকে সহজ ভাবে উপস্থাপন করার দরকার হলে এই প্যাটার্ন ব্যাবহার করা হয়।

                +

                ধরুন আপনার সিস্টেম কিংবা অ্যাপ্লিকেশনে একটা কমপ্লেক্স লাইব্রেরি ব্যাবহার করার দরকার পরতেছে আর আপনি উক্ত কমপ্লেক্স পার্টকে সহজ করে তোলার জন্য একটা Wrapper বানিয়ে সেইটা করতে পারেন।

                +

                এবার নিচে একটা উদাহরণের মাধ্যমে প্যাটার্নটি বোঝানোর চেষ্টা করা হলঃ

                +
                <?php
                +
                +class Cart
                +{
                +    public function addProducts($products)
                +    {
                +        // Product adding codes goes here
                +    }
                +
                +    public function getProducts()
                +    {
                +        // Product retrieval codes goes here
                +    }
                +}
                +
                +class Order
                +{
                +    public function process($products)
                +    {
                +        // Order processing codes goes here
                +    }
                +}
                +
                +class Payment
                +{
                +    public function charge($charge)
                +    {
                +        // Additional charge codes goes here
                +    }
                +
                +    public function makePayment()
                +    {
                +        // Payment method verify & payment codes goes here
                +    }
                +}
                +
                +class Shipping
                +{
                +    public function calculateCharge()
                +    {
                +        // Calculation codes goes here
                +    }
                +
                +    public function shipProducts()
                +    {
                +        // Ship process codes goes here
                +    }
                +}
                +
                +class CustomerFacade
                +{
                +    public function __construct()
                +    {
                +        $this->cart = new Cart;
                +        $this->order = new Order;
                +        $this->payment = new Payment;
                +        $this->shipping = new Shipping;
                +    }
                +
                +    public function addToCart($products)
                +    {
                +        $this->cart->addProducts($products);
                +    }
                +
                +    public function checkout()
                +    {
                +        $products = $this->cart->getProducts();
                +
                +        $this->totalAmount = $this->order->process($products);
                +    }
                +
                +    public function makePayment()
                +    {
                +        $charge = $this->shipping->calculateCharge();
                +        $this->payment->charge($charge);
                +
                +        $isCompleted = $this->payment->makePayment();
                +
                +        if ($isCompleted) {
                +            $this->shipping->shipProducts();
                +        }
                +    }
                +}
                +
                +$customer = new CustomerFacade;
                +
                +$products = [
                +    [
                +        'name' => 'Polo T-Shirt',
                +        'price' => 40,
                +    ],
                +    [
                +        'name' => 'Smart Watch',
                +        'price' => 400,
                +    ],
                +];
                +
                +$customer->addToCart($products);
                +$customer->checkout();
                +$customer->makePayment();
                +
                +

                উপরের কোডটি খেয়াল করলে দেখতে পারবেন এখানে একটা ই-কমার্স অ্যাপ্লিকেশনের প্রসেস দেখানো হয়েছে। এর জন্য আমরা যথাক্রমে Cart, Order, Payment, Shipping ক্লাসগুলো ব্যাবহার করেছি আর ফ্যাসাড হিসেবে CustomerFacade ক্লাস ব্যাবহার করেছি। এখানে কোন প্রোডাক্টকে কার্টে যুক্ত করার জন্য Cart ক্লাসটি, অর্ডার প্রসেস করার জন্য Order ক্লাসটি, পেমেন্ট প্রসেস করার জন্য Payment ক্লাসটি আর প্রডাক্ট এর শিপিং হ্যান্ডল করার জন্য Shipping ক্লাসটি ব্যাবহার করেছি।

                +

                এখন মুল কথা হল আমরা যদি এসব কাজের জন্য প্রতিবার উক্ত ক্লাস গুলোকে বার বার কল করি তাহলে অনেক সময় সাপেক্ষ বেপার হয়ে পরবে আর স্ট্রাকচারটিও ভাল হবেনা। আর তাই এখানে ফ্যাসাড প্যাটার্নটি ব্যাবহার করা হয়েছে। যাতে ডেভেলপার কিংবা ক্লায়েন্ট হিসেবে সুধু মাত্র CustomerFacade ক্লাসটিকে ব্যাবহার করে উপরে উল্লেখিত সবগুলো কাজ অনায়াসে করা সম্ভব।

                +

                অতিরিক্ত বিষয় (লারাভেল ফ্যাসাড) ঃ

                +

                আমরা যারা লারাভেল ব্যাবহার করি তারা কম বেশি সবাই জানি লারাভেল এ অনেকগুলো বিল্ড-ইন ফ্যাসাড আছে কিংবা ব্যাবহার হয়। যেমনঃ DB, View, Event, Queue, Mail ইত্যাদি।

                +

                আমরা মূলত যেটা জানি তা হল লারাভেল এ ফ্যাসাড Statically কোন ক্লাসকে কল করার জন্য ব্যাবহার হয়। আসলে বিষয়টি ঠিক তেমন নয়। এখানে অনেক কমপ্লেক্স সিস্টেমকে হাইড করে আমাদের কাছে সহজ ভাবে উপস্থাপন করা হয়েছে তার সাথে লারাভেল ফ্যাসাড প্যাটার্নের সাথে __callStatic ম্যাজিক মেথডটি ব্যাবহার করা হয়েছে। যাতে ডেভেলপার কিংবা ক্লায়েন্টকে আলাদাভাবে ক্লাস ইন্সট্যানশিয়েট করতে না হয়।

                +

                নিচে একটা উদাহরণ দেয়া হলঃ

                +
                <?php
                +
                +class Person
                +{
                +    public function getFullName()
                +    {
                +        return 'Sohel Amin';
                +    }
                +}
                +
                +class PersonFacade
                +{
                +    static $instance;
                +
                +    public static function __callStatic($method, $args)
                +    {
                +        if (null === static::$instance) {
                +            static::$instance = new Person;
                +        }
                +
                +        $instance = static::$instance;
                +
                +        switch (count($args)) {
                +            case 0:
                +                return $instance->$method();
                +            case 1:
                +                return $instance->$method($args[0]);
                +            case 2:
                +                return $instance->$method($args[0], $args[1]);
                +            case 3:
                +                return $instance->$method($args[0], $args[1], $args[2]);
                +            case 4:
                +                return $instance->$method($args[0], $args[1], $args[2], $args[3]);
                +            default:
                +                return call_user_func_array([$instance, $method], $args);
                +        }
                +
                +    }
                +}
                +
                +var_dump(PersonFacade::getFullName());
                +
                +

                এই চ্যাপ্টারের সোর্স কোডটি এই লিঙ্ক থেকে পাবেন।

                + + +
                + +
                +
                +
                + +

                results matching ""

                +
                  + +
                  +
                  + +

                  No results matching ""

                  + +
                  +
                  +
                  + +
                  +
                  + +
                  + + + + + + + + + + + + + + +
                  + + +
                  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/factory-pattern.html b/_book/design-patterns/factory-pattern.html new file mode 100644 index 0000000..b952b59 --- /dev/null +++ b/_book/design-patterns/factory-pattern.html @@ -0,0 +1,1165 @@ + + + + + + ফ্যাক্টরী · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                  +
                  + + + + + + + + +
                  + +
                  + +
                  + + + + + + + + +
                  +
                  + +
                  +
                  + +
                  + +

                  ফ্যাক্টরী

                  +

                  ফ্যাক্টরী প্যাটার্ন এমন একটি প্যাটার্ন যা কম বেশি সব ধরনের অ্যাপ্লিকেশনে ব্যাবহৃত হয়ে থাকে এইটা ক্রিয়েশনাল প্যাটার্ন ক্যাটাগরীর মধ্যে পরে।

                  +

                  ফ্যাক্টরী প্যাটার্নের মূল উদ্দেশ্যই হল এর প্রোডাক্ট কিংবা চাইল্ড ক্লাসের অবজেক্ট তৈরি করে দেয়া। যেমন বাস্তব জীবনে যেভাবে ফ্যাক্টরীতে প্রোডাক্ট তৈরি হয়ে থাকে।

                  +

                  এই প্যাটার্ন ক্লাইন্টের কাছে অবজেক্ট ইনস্টানশিয়েট করার লজিক অদৃশ্যমান রাখে। আর অবজেক্টের ক্লাস গুলা একটা কমন ইন্টারফেইস কে ফলো করে বানানো থাকে।

                  +

                  এই প্যাটার্ন সাধারণত ৩ প্রকারেরঃ ১. সিম্পল ফ্যাক্টরী। ২. ফ্যাক্টরী মেথড। ৩. অ্যাবস্ট্রাক্ট ফ্যাক্টরী।

                  +

                  ১. সিম্পল ফ্যাক্টরীঃ

                  +

                  ফ্যাক্টরী প্যাটার্নের মধ্যে সিম্পল ফ্যাক্টরী হচ্ছে সবচেয়ে সহজ প্যাটার্ন যদিও অফিশিয়ালি এই প্যাটার্ন ডিজাইন প্যাটার্ন হিসেবে স্বীকৃত না।

                  +

                  এই প্যাটার্নের নিয়ম মতে এর একটি ফ্যাক্টরী থাকবে আর একটি ফ্যাক্টরী একই সময় শুধুমাত্র একটাই প্রোডাক্ট তৈরি করবে অর্থাৎ একটিই ইনস্টান্স কিংবা অবজেক্ট রিটার্ন করবে।

                  +

                  নিচে একটা উদাহরণ দেয়া হলঃ

                  +
                  class CarFactory
                  +{
                  +    protected $brands = [];
                  +
                  +    public function __construct()
                  +    {
                  +        $this->brands = [
                  +            'mercedes' => 'MercedesCar',
                  +            'toyota' => 'ToyotaCar',
                  +        ];
                  +    }
                  +
                  +    public function make($brand)
                  +    {
                  +        if (!array_key_exists($brand, $this->brands)) {
                  +            return new Exception('Not available this car');
                  +        }
                  +
                  +        $className = $this->brands[$brand];
                  +
                  +        return new $className();
                  +    }
                  +}
                  +
                  +interface CarInterface
                  +{
                  +    public function design();
                  +    public function assemble();
                  +    public function paint();
                  +}
                  +
                  +class MercedesCar implements CarInterface
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Mercedes Car';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Mercedes Car';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Mercedes Car';
                  +    }
                  +}
                  +
                  +class ToyotaCar implements CarInterface
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Toyota Car';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Toyota Car';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Toyota Car';
                  +    }
                  +}
                  +
                  +$carFactory = new CarFactory;
                  +
                  +$mercedes = $carFactory->make('mercedes');
                  +echo $mercedes->design() . '<br/>';
                  +echo $mercedes->assemble() . '<br/>';
                  +echo $mercedes->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$toyota = $carFactory->make('toyota');
                  +echo $toyota->design() . '<br/>';
                  +echo $toyota->assemble() . '<br/>';
                  +echo $toyota->paint() . '<br/>';
                  +
                  +

                  এখানে CarFactory নামে মূল ফ্যাক্টরী ক্লাস ডিফাইন করা হয়েছে যেটির মাধ্যমে একটা Car ইনস্টান্স তৈরি করা হবে। Car এর জন্য ২ টি ক্লাস যথাক্রমে MercedesCarToyotaCar ডিফাইন করা হয়েছে যেগুলো CarInterface কে ফলো করেছে।

                  +

                  এবার চলুন CarFactory ক্লাসটিকে ইনস্টানশিয়েট করি।

                  +
                  $carFactory = new CarFactory;
                  +
                  +

                  এরপর ধরুন MercedesCar ক্লাসকে ফ্যাক্টরির মাধ্যমে ইনস্টানশিয়েট করব তাহলে টাইপ/প্যারামিটার হিসেবে mercedes দিতে হবে নিচের মত করে।

                  +
                  $mercedes = $carFactory->make('mercedes');
                  +echo $mercedes->design() . '<br/>';
                  +echo $mercedes->assemble() . '<br/>';
                  +echo $mercedes->paint() . '<br/>';
                  +
                  +

                  অনুরূপ ভাবে ToyotaCar ক্লাসকে ইনস্টানশিয়েট করতে হলে

                  +
                  $toyota = $carFactory->make('toyota');
                  +echo $toyota->design() . '<br/>';
                  +echo $toyota->assemble() . '<br/>';
                  +echo $toyota->paint() . ‘<br/>';
                  +
                  +

                  আর ডিফাইন না করা কোন ক্লাসের টাইপ দিলে সেটি এরর দেখাবে।

                  +

                  ২. ফ্যাক্টরী মেথডঃ

                  +

                  ফ্যাক্টরী মেথড প্যাটার্ন অনেকখানি সিম্পল ফ্যাক্টরী প্যাটার্নের মতই শুধুমাত্র এর মূল পার্থক্য হল এটি তার সাব ক্লাস গুলোকে ক্লাস ইনস্টানশিয়েট করার স্বাধীনতা দিয়ে দেয়। আর এর একাধিক ফ্যাক্টরী থাকতে পারে।

                  +

                  নিচে একটা উদাহরণ দেয়া হলঃ

                  +
                  abstract class VehicleFactoryMethod
                  +{
                  +    abstract public function make($brand);
                  +}
                  +
                  +class CarFactory extends VehicleFactoryMethod
                  +{
                  +    public function make($brand)
                  +    {
                  +        $car = null;
                  +
                  +        switch ($brand) {
                  +            case "mercedes":
                  +                $car = new MercedesCar;
                  +                break;
                  +            case "toyota":
                  +                $car = new ToyotaCar;
                  +                break;
                  +        }
                  +
                  +        return $car;
                  +    }
                  +}
                  +
                  +class BikeFactory extends VehicleFactoryMethod
                  +{
                  +    public function make($brand)
                  +    {
                  +        $bike = null;
                  +
                  +        switch ($brand) {
                  +            case "yamaha":
                  +                $bike = new YamahaBike;
                  +                break;
                  +            case "ducati":
                  +                $bike = new DucatiBike;
                  +                break;
                  +        }
                  +
                  +        return $bike;
                  +    }
                  +}
                  +
                  +interface CarInterface
                  +{
                  +    public function design();
                  +
                  +    public function assemble();
                  +
                  +    public function paint();
                  +}
                  +
                  +interface BikeInterface
                  +{
                  +    public function design();
                  +
                  +    public function assemble();
                  +
                  +    public function paint();
                  +}
                  +
                  +class MercedesCar implements CarInterface
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Mercedes Car';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Mercedes Car';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Mercedes Car';
                  +    }
                  +}
                  +
                  +class ToyotaCar implements CarInterface
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Toyota Car';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Toyota Car';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Toyota Car';
                  +    }
                  +}
                  +
                  +class YamahaBike implements BikeInterface
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Yamaha Bike';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Yamaha Bike';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Yamaha Bike';
                  +    }
                  +}
                  +
                  +class DucatiBike implements BikeInterface
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Ducati Bike';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Ducati Bike';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Ducati Bike';
                  +    }
                  +}
                  +
                  +$carFactoryInstance = new CarFactory;
                  +
                  +$mercedes = $carFactoryInstance->make('mercedes');
                  +echo $mercedes->design() . '<br/>';
                  +echo $mercedes->assemble() . '<br/>';
                  +echo $mercedes->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$toyota = $carFactoryInstance->make('toyota');
                  +echo $toyota->design() . '<br/>';
                  +echo $toyota->assemble() . '<br/>';
                  +echo $toyota->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$bikeFactoryInstance = new BikeFactory;
                  +
                  +$yamaha = $bikeFactoryInstance->make('yamaha');
                  +echo $yamaha->design() . '<br/>';
                  +echo $yamaha->assemble() . '<br/>';
                  +echo $yamaha->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$ducati = $bikeFactoryInstance->make('ducati');
                  +echo $ducati->design() . '<br/>';
                  +echo $ducati->assemble() . '<br/>';
                  +echo $ducati->paint() . '<br/>';
                  +
                  +

                  এখানে ফ্যাক্টরী মেথডের জন্য VehicleFactoryMethod নামে একটা অ্যাবস্ট্রাক্ট ক্লাস ডিফাইন করা হয়েছে যেটির সাব ক্লাস যথাক্রমে CarFactoryBikeFactory আছে যেগুলা ভিন্ন ভিন্ন একক ফ্যাক্টরী। আবার প্রতিটি ফ্যাক্টরীর জন্য সিম্পল ফ্যাক্টরী প্যাটার্নের ন্যায় ইন্টারফেইস CarInterfaceBikeInterface ডিফাইন করা হয়েছে যেগুলোকে ইমপ্লিমেন্ট করে কংক্রিট ক্লাস অর্থাৎ ইনস্টানশিয়েট যোগ্য ক্লাস যথাক্রমে CarFactory এর আওতায় MercedesCarToyotaCar এবং BikeFactory এর আওতায় YamahaBikeDucatiBike ডিফাইন করা হয়েছে।

                  +

                  সুতরাং CarFactoryBikeFactory ক্লাসগুলো নির্ধারণ করতে পারবে সে কোন ক্লাসকে ইনস্টানশিয়েট করবে।

                  +

                  নিচের কোডটি খেয়াল করলে বুঝতে পারবেন ২ টি আলাদা ফ্যাক্টরীর মাধ্যমে প্যারামিটার কিংবা Car এর ব্র্যান্ড পাস করে কাঙ্ক্ষিত অবজেক্ট কে পাওয়া যায়।

                  +
                  $carFactoryInstance = new CarFactory;
                  +
                  +$mercedes = $carFactoryInstance->make('mercedes');
                  +echo $mercedes->design() . '<br/>';
                  +echo $mercedes->assemble() . '<br/>';
                  +echo $mercedes->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$toyota = $carFactoryInstance->make('toyota');
                  +echo $toyota->design() . '<br/>';
                  +echo $toyota->assemble() . '<br/>';
                  +echo $toyota->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$bikeFactoryInstance = new BikeFactory;
                  +
                  +$yamaha = $bikeFactoryInstance->make('yamaha');
                  +echo $yamaha->design() . '<br/>';
                  +echo $yamaha->assemble() . '<br/>';
                  +echo $yamaha->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$ducati = $bikeFactoryInstance->make('ducati');
                  +echo $ducati->design() . '<br/>';
                  +echo $ducati->assemble() . '<br/>';
                  +echo $ducati->paint() . ‘<br/>';
                  +
                  +

                  ৩. অ্যাবস্ট্রাক্ট ফ্যাক্টরীঃ

                  +

                  অ্যাবস্ট্রাক্ট ফ্যাক্টরী এমন একটি পদ্ধতি প্রদান করে যেখানে একটি মূল (অ্যাবস্ট্রাক্ট) ফ্যাক্টরী অনেকগুলো একক ফ্যাক্টরীকে একত্রিত করে রাখে।

                  +

                  এক কথায়, প্রথমে একটি অ্যাবস্ট্রাক্ট ফ্যাক্টরী অনেকগুলো প্রোডাক্ট ফ্যাক্টরী তৈরি করে এরপর প্রতিটি ফ্যাক্টরী একাধিক প্রোডাক্ট কিংবা অবজেক্ট তৈরি করে।

                  +

                  উল্লেখ্য, প্রতিটি প্রোডাক্ট ফ্যাক্টরী ক্লাসকে একটা কমন অ্যাবস্ট্রাক্ট ক্লাসকে এক্সটেন্ড করতে হবে অথবা একটা কমন ইন্টারফেইসকে ইমপ্লিমেন্ট করতে হবে। আবার প্রতিটি প্রোডাক্ট ফ্যাক্টরী ক্লাসে একাধিক আর একই মেথড থাকতে হবে।

                  +

                  নিচে একটা উদাহরণ দেয়া হলঃ

                  +
                  abstract class AbstractVehicleFactory
                  +{
                  +    abstract public function makeCar();
                  +    abstract public function makeBike();
                  +}
                  +
                  +class BangladeshiFactory extends AbstractVehicleFactory
                  +{
                  +    public function makeCar()
                  +    {
                  +        return new ToyotaCar();
                  +    }
                  +
                  +    public function makeBike()
                  +    {
                  +        return new YamahaBike();
                  +    }
                  +}
                  +
                  +class USAFactory extends AbstractVehicleFactory
                  +{
                  +    public function makeCar()
                  +    {
                  +        return new MercedesCar();
                  +    }
                  +
                  +    public function makeBike()
                  +    {
                  +        return new DucatiBike();
                  +    }
                  +}
                  +
                  +abstract class AbstractVehicle
                  +{
                  +    abstract public function design();
                  +    abstract public function assemble();
                  +    abstract public function paint();
                  +}
                  +
                  +abstract class AbstractCarVehicle extends AbstractVehicle
                  +{
                  +
                  +}
                  +
                  +abstract class AbstractBikeVehicle extends AbstractVehicle
                  +{
                  +
                  +}
                  +
                  +class MercedesCar extends AbstractCarVehicle
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Mercedes Car';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Mercedes Car';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Mercedes Car';
                  +    }
                  +}
                  +
                  +class ToyotaCar extends AbstractCarVehicle
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Toyota Car';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Toyota Car';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Toyota Car';
                  +    }
                  +}
                  +
                  +class YamahaBike extends AbstractBikeVehicle
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Yamaha Bike';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Yamaha Bike';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Yamaha Bike';
                  +    }
                  +}
                  +
                  +class DucatiBike extends AbstractBikeVehicle
                  +{
                  +    public function design()
                  +    {
                  +        return 'Designing Ducati Bike';
                  +    }
                  +
                  +    public function assemble()
                  +    {
                  +        return 'Assembling Ducati Bike';
                  +    }
                  +
                  +    public function paint()
                  +    {
                  +        return 'Painting Ducati Bike';
                  +    }
                  +}
                  +
                  +$bangladeshiFactoryInstance = new BangladeshiFactory;
                  +$car = $bangladeshiFactoryInstance->makeCar();
                  +echo $car->design() . '<br/>';
                  +echo $car->assemble() . '<br/>';
                  +echo $car->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$bike = $bangladeshiFactoryInstance->makeBike();
                  +echo $bike->design() . '<br/>';
                  +echo $bike->assemble() . '<br/>';
                  +echo $bike->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$usaFactoryInstance = new USAFactory;
                  +$car = $usaFactoryInstance->makeCar();
                  +echo $car->design() . '<br/>';
                  +echo $car->assemble() . '<br/>';
                  +echo $car->paint() . '<br/>';
                  +
                  +echo '<br/>';
                  +
                  +$bike = $usaFactoryInstance->makeBike();
                  +echo $bike->design() . '<br/>';
                  +echo $bike->assemble() . '<br/>';
                  +echo $bike->paint() . ‘<br/>';
                  +
                  +

                  উপরের কোডে AbstractVehicleFactory নামে একটা অ্যাবস্ট্রাক্ট ফ্যাক্টরী ক্লাস ডিফাইন করা হয়েছে যেখানে makeCar()makeBike() ২টা মেথড দেয়া আছে যাতে সাব ফ্যাক্টরী গুলো ওই মেথড গুলো ডিফাইন করে।

                  +

                  এখানে একটি মেথড Car অবজেক্ট তৈরি করতে আরেকটি Bike অবজেক্ট তৈরি করতে ব্যবহৃত হয়েছে যা সব গুলা ফ্যাক্টরীকেই করতে হবে। আর মূল বিষয় হল একেক ফ্যাক্টরী একেক ব্র্যান্ডের CarBike অবজেক্ট তৈরি করবে।

                  +

                  যেমন এখানে আমরা BangladeshiFactory ফ্যাক্টরী ব্যাবহার করেছি যেটি ToyotaCarYamahaBike ক্লাসের অবজেক্ট তৈরি করবে। অনুরূপ ভাবে, USAFactory ফ্যাক্টরী MercedesCarDucatiBike ক্লাসের অবজেক্ট তৈরি করবে।

                  +

                  আবার আপনি চাইলে একটা ফ্যাক্টরীতে একাধিক ব্রান্ডের Car কিংবা Bike এর অবজেক্ট তৈরি করতে পারেন সেক্ষেত্রে র‍্যান্ডমলি কিংবা লজিক্যালি করতে হবে।

                  +

                  এই লিঙ্ক থেকে সোর্স কোডটি পাবেন।

                  + + +
                  + +
                  +
                  +
                  + +

                  results matching ""

                  +
                    + +
                    +
                    + +

                    No results matching ""

                    + +
                    +
                    +
                    + +
                    +
                    + +
                    + + + + + + + + + + + + + + +
                    + + +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/index.html b/_book/design-patterns/index.html new file mode 100644 index 0000000..d8a6c50 --- /dev/null +++ b/_book/design-patterns/index.html @@ -0,0 +1,722 @@ + + + + + + ডিজাইন প্যাটার্ন · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    +
                    + + + + + + + + +
                    + +
                    + +
                    + + + + + + + + +
                    +
                    + +
                    +
                    + +
                    + +

                    ডিজাইন প্যাটার্ন

                    +

                    সফটওয়্যার ইঞ্জিনিয়ারিং এ ডিজাইন প্যাটার্ন হল কোডের সাধারণ সমস্যার রি-ইউজিবিলিটি বাড়ানোর জন্য এক প্রকারের নিয়মনীতি অথবা টেম্পলেট। যাতে করে সফটওয়্যার একটা নির্দিষ্ট আর্কিটেকচার এ তৈরি করা যায় আর কোডের পুনুরাব্রিত্তি ঠেকান যায়।

                    +

                    ডিজাইন প্যাটার্ন সাধারণত নিম্মলিখিত ক্যাটাগরীর হয়ে থাকেঃ

                    +
                      +
                    1. Creational
                    2. +
                    3. Structural
                    4. +
                    5. Behavioural
                    6. +
                    +

                    আমরা বহুল ব্যাবহ্রিত গুলো নিয়ে আলোচনা করব।

                    +

                    টপিকস লিস্ট

                    + + + +
                    + +
                    +
                    +
                    + +

                    results matching ""

                    +
                      + +
                      +
                      + +

                      No results matching ""

                      + +
                      +
                      +
                      + +
                      +
                      + +
                      + + + + + + + + + + + + + + +
                      + + +
                      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/iterator-pattern.html b/_book/design-patterns/iterator-pattern.html new file mode 100644 index 0000000..e09335b --- /dev/null +++ b/_book/design-patterns/iterator-pattern.html @@ -0,0 +1,788 @@ + + + + + + ইটারেটর · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                      +
                      + + + + + + + + +
                      + +
                      + +
                      + + + + + + + + +
                      +
                      + +
                      +
                      + +
                      + +

                      ইটারেটর

                      +

                      ইটারেটর ডিজাইন প্যাটার্ন বিহেভিওরাল টাইপের মধ্যে পরে। এই প্যাটার্ন এর মুল উদ্দেশ্যই হচ্ছে ইটারেটরের ব্যাবহার করা। ইটারেটর একটা কন্টেইনার কিংবা অবজেক্ট এর ইলিমেন্টকে ট্রাভার্স করার জন্য সহায়তা করে আর এতে ভিতরের লজিক গুলো লুকানো অবস্থায় থাকে। যারফলে, আমরা কন্টেইনারে আমাদের পছন্দের মত ডাটা স্ট্রাকচার ব্যাবহার করতে পারি।

                      +

                      এবার চলুন আমরা কিভাবে এই প্যাটার্নটি ইমপ্লিমেন্ট করতে পারি। পিএইচপির একটা বিল্ড-ইন Iterator ইন্টারফেইস আছে আমরা সেটি ব্যাবহার করব।

                      +

                      সর্বপ্রথমে, আমরা ইলিমেন্ট বা আইটেম এর জন্য Book নামে একটা ক্লাস ডিফাইন করব।

                      +
                      class Book
                      +{
                      +    private $title;
                      +
                      +    public function __construct($title)
                      +    {
                      +        $this->title = $title;
                      +    }
                      +
                      +    public function getTitle()
                      +    {
                      +        return $this->title;
                      +    }
                      +}
                      +
                      +

                      এবার কন্টেইনার এর জন্য BookList নামে একটা ক্লাস ডিফাইন করব।

                      +
                      class BookList implements Iterator, Countable
                      +{
                      +    private $books = [];
                      +
                      +    private $currentIndex = 0;
                      +
                      +    public function current()
                      +    {
                      +        return $this->books[$this->currentIndex];
                      +    }
                      +
                      +    public function key()
                      +    {
                      +        return $this->currentIndex;
                      +    }
                      +
                      +    public function next()
                      +    {
                      +        $this->currentIndex++;
                      +    }
                      +
                      +    public function rewind()
                      +    {
                      +        $this->currentIndex = 0;
                      +    }
                      +
                      +    public function valid()
                      +    {
                      +        return isset($this->books[$this->currentIndex]);
                      +    }
                      +
                      +    public function count()
                      +    {
                      +        return count($this->books);
                      +    }
                      +
                      +    public function addBook(Book $book)
                      +    {
                      +        $this->books[] = $book;
                      +    }
                      +
                      +    public function removeBook(Book $bookToRemove)
                      +    {
                      +        foreach ($this->books as $key => $book) {
                      +            if ($book->getTitle() === $bookToRemove->getTitle()) {
                      +                unset($this->books[$key]);
                      +            }
                      +        }
                      +
                      +        $this->books = array_values($this->books);
                      +    }
                      +}
                      +
                      +

                      এখানে Iterator ইন্টারফেসের জন্য যথাক্রমে current(), key(), next(), rewind()valid() মেথডগুলি ইমপ্লিমেন্ট করা হয়েছে আর Countable ইন্টারফেইসের এর জন্য count() মেথডটি ইমপ্লিমেন্ট করা হয়েছে যা ইলেমেন্ট কাউন্ট করতে সাহায্য করবে। আর ইলিমেন্ট অ্যাড আর রিমুভ করার জন্য addBook()removeBook() কাস্টম মেথডগুলি ব্যাবহার করা হয়েছে।

                      +

                      এবার কন্টেইনার ক্লাসটি ইন্সটানশিয়েট করে কিছু ইলিমেন্ট অ্যাড করে আমরা নিচের ন্যায় লুপের মাধ্যমে ইলিমেন্ট ট্রাভার্স করে অ্যাকসেস করতে পারি।

                      +
                      $bookList = new BookList();
                      +$bookList->addBook(new Book('Design Pattern'));
                      +$bookList->addBook(new Book('Head First Design Pattern'));
                      +$bookList->addBook(new Book('Clean Code'));
                      +$bookList->addBook(new Book('The Pragmatic Programmer'));
                      +
                      +$bookList->removeBook(new Book('Design Pattern'));
                      +
                      +foreach ($bookList as $book) {
                      +    echo $book->getTitle() . PHP_EOL;
                      +}
                      +
                      +

                      এই চ্যাপ্টারের সোর্স কোডটি এই লিঙ্ক থেকে পাবেন।

                      + + +
                      + +
                      +
                      +
                      + +

                      results matching ""

                      +
                        + +
                        +
                        + +

                        No results matching ""

                        + +
                        +
                        +
                        + +
                        +
                        + +
                        + + + + + + + + + + + + + + +
                        + + +
                        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/observer-pattern.html b/_book/design-patterns/observer-pattern.html new file mode 100644 index 0000000..44d6581 --- /dev/null +++ b/_book/design-patterns/observer-pattern.html @@ -0,0 +1,861 @@ + + + + + + অবজার্ভার · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                        +
                        + + + + + + + + +
                        + +
                        + +
                        + + + + + + + + +
                        +
                        + +
                        +
                        + +
                        + +

                        অবজার্ভার

                        +

                        অবজার্ভার ডিজাইন প্যাটার্ন বিহেভিওরাল টাইপের মধ্যে পরে। এটা pub/sub এর নিয়মে কাজ করে অর্থাৎ কোন অবজেক্ট কিংবা সাবজেক্ট এ পরিবর্তন হলে সেটা Publisher তৎক্ষন্যাত Subscriber দেরকে জানায় দিবে কিংবা নটিফাই করবে।

                        +

                        পিএইসপিতে অবজার্ভার প্যাটার্নটি প্রয়োগ করতে হলে যথাক্রমে SplSubjectSplObserver ইন্টারফেইস ইমপ্লিমেন্ট করে সাবজেক্ট ও অবজার্ভার ২ টা ক্লাস লিখতে হয়। আর সাবস্ক্রাইব করা অবজার্ভারদেরকে স্টোর করে রাখার জন্য SplObjectStorage এই ক্লাসটিকে ব্যাবহার করা যেতে পারে।

                        +

                        উপরে উল্লেখিত SplSubject, SplObserver, SplObjectStorage হল পিএইসপির Standard PHP Library (SPL)

                        +

                        নিচে একটি Model নামক ক্লাস ও দুইটি অবজার্ভার ক্লাসের উদাহরণ দেয়া হলঃ

                        +
                        <?php
                        +
                        +class Model implements SplSubject
                        +{
                        +    protected $observers;
                        +
                        +    public function __construct()
                        +    {
                        +        $this->observers = new SplObjectStorage();
                        +    }
                        +
                        +    public function attach(SplObserver $observer)
                        +    {
                        +        $this->observers->attach($observer);
                        +    }
                        +
                        +    public function detach(SplObserver $observer)
                        +    {
                        +        $this->observers->detach($observer);
                        +    }
                        +
                        +    public function notify()
                        +    {
                        +        foreach ($this->observers as $observer) {
                        +            $observer->update($this);
                        +        }
                        +    }
                        +
                        +    public function __set($name, $value)
                        +    {
                        +        $this->data[$name] = $value;
                        +        // notify the observers, that model has been updated
                        +        $this->notify();
                        +    }
                        +}
                        +
                        +class ModelObserver implements SplObserver
                        +{
                        +    public function update(SplSubject $subject)
                        +    {
                        +        echo get_class($subject) . ' has been updated' . '<br>';
                        +    }
                        +}
                        +
                        +class Observer2 implements SplObserver
                        +{
                        +    public function update(SplSubject $subject)
                        +    {
                        +        echo get_class($subject) . ' has been updated' . '<br>';
                        +    }
                        +}
                        +
                        +// Instantiate the model class for 2 different objects
                        +$model1 = new Model();
                        +$model2 = new Model();
                        +
                        +// Instantiate the observers
                        +$modelObserver = new ModelObserver();
                        +$observer2 = new Observer2();
                        +
                        +// Attach the observers to $model1
                        +$model1->attach($modelObserver);
                        +$model1->attach($observer2);
                        +
                        +// Attach the observers to $model2
                        +$model2->attach($observer2);
                        +
                        +// Changing the subject properties
                        +$model1->title = 'Hello World';
                        +$model2->body = 'Lorem ipsum............';
                        +
                        +

                        উপরে Model ক্লাসটি হল সাবজেক্ট ModelObserverObserver2 হল অবজার্ভার।

                        +

                        Model ক্লাসটি যেহেতু SplSubject ইন্টারফেইস ইমপ্লিমেন্ট করে লেখা হয়েছে কাজেই attach(), detach()notify() মেথডগুলা অবশ্যই থাকতে হবে।

                        +

                        অপরদিকে যেহেতু ModelObserverObserver2 ক্লাসগুলা SplObserver ইন্টারফেইস ইমপ্লিমেন্ট করে লেখা হয়েছে সেহেতু update() মেথডটি ক্লাসগুলাতে থাকতে হবে।

                        +

                        এবার আপনারা যদি SplSubjectSplObserver ইন্টারফেইস ব্যাবহার না করে অবজার্ভার ডিজাইন প্যাটার্ন এর প্রয়োগ করতে চান সেটাও করতে পারবেন শুধুমাত্র আপনার বিষয় বস্তু ঠিক থাকলেই হল।

                        +

                        নিচে একটা উদাহরণ দেয়া হলঃ

                        +
                        <?php
                        +
                        +class Model
                        +{
                        +    protected $observers;
                        +
                        +    public function __construct()
                        +    {
                        +        $this->observers = new SplObjectStorage();
                        +    }
                        +
                        +    public function notify()
                        +    {
                        +        foreach ($this->observers as $observer) {
                        +            $observer->update($this);
                        +        }
                        +    }
                        +
                        +    public function setObservers($observers = [])
                        +    {
                        +        foreach ($observers as $observer) {
                        +            $this->observers->attach($observer);
                        +        }
                        +    }
                        +
                        +    public function __set($name, $value)
                        +    {
                        +        $this->data[$name] = $value;
                        +        // notify the observers, that model has been updated
                        +        $this->notify();
                        +    }
                        +}
                        +
                        +class Post extends Model
                        +{
                        +    public function insert($data)
                        +    {
                        +        // Store the data
                        +        // Notify to observers
                        +        $this->notify();
                        +    }
                        +
                        +    public function update($data)
                        +    {
                        +        // Update the model
                        +        // Notify to observers
                        +        $this->notify();
                        +    }
                        +
                        +    public function delete($id)
                        +    {
                        +        // Delete the model
                        +        // Notify to observers
                        +        $this->notify();
                        +    }
                        +}
                        +
                        +class PostModelObserver
                        +{
                        +    public function update($subject)
                        +    {
                        +        echo get_class($subject) . ' has been updated' . '<br>';
                        +    }
                        +}
                        +
                        +class Observer2
                        +{
                        +    public function update($subject)
                        +    {
                        +        echo get_class($subject) . ' has been updated' . '<br>';
                        +    }
                        +}
                        +
                        +$post = new Post();
                        +
                        +$post->setObservers([new PostModelObserver, new Observer2]);
                        +
                        +$post->title = 'Hello World';
                        +
                        +

                        এই লিঙ্ক থেকে আরও ধারনা পেতে পারেন।

                        + + +
                        + +
                        +
                        +
                        + +

                        results matching ""

                        +
                          + +
                          +
                          + +

                          No results matching ""

                          + +
                          +
                          +
                          + +
                          +
                          + +
                          + + + + + + + + + + + + + + +
                          + + +
                          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/proxy-pattern.html b/_book/design-patterns/proxy-pattern.html new file mode 100644 index 0000000..63ecbc5 --- /dev/null +++ b/_book/design-patterns/proxy-pattern.html @@ -0,0 +1,786 @@ + + + + + + প্রক্সি · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                          +
                          + + + + + + + + +
                          + +
                          + +
                          + + + + + + + + +
                          +
                          + +
                          +
                          + +
                          + +

                          প্রক্সি

                          +

                          Proxy ডিজাইন প্যাটার্ন স্ট্রাকচারাল ডিজাইন প্যাটার্নের মধ্যে পরে। এই প্যাটার্ন শুরুর আগে আসুন আমরা “প্রক্সি” শব্দের অর্থ জেনে নেই। প্রক্সি এমন একটি প্রতিনিধি বা বস্তু যা অন্য বিষয় বস্তুর হয়ে কাজ করে।

                          +

                          অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং এ প্রক্সি হলঃ একটি অবজেক্ট অন্য কোন অবজেক্টের হয়ে কাজ করা বা তাকে কন্ট্রোল করা।

                          +

                          প্রক্সি সাধারণত ৩ প্রকারেরঃ 1. Virtual Proxy: এই প্রক্সি মুল অবজেক্টকে ইন্সটানশিয়েট বা ইনিশিয়ালাইজ করতে বিলম্ব করে যতক্ষণ না দরকার পরে। 2. Remote Proxy: এই প্রক্সি কোন রিমুট লোকেশনে অবস্থিত কোন অবজেক্টকে রিপ্রেজেন্ট করে। যেমনঃ সার্ভার থেকে কোন অবজেক্টকে অ্যাকসেস করা। 3. Protection Proxy: এই প্রক্সি মুল অবজেক্টকে অ্যাকসেস করার আগে সেকুরিটি চেক করে। 4. Smart Proxy: এই প্রক্সি মুল অবজেক্টের রেফারেন্স নাম্বার ট্রাক করে এবং প্রয়োজন মত মেমোরি থেকে লোডিং অথবা ফ্রি করতে সহয়তা করে।

                          +

                          এখানে আমরা Virtual Proxy এর একটি উদাহরণ দেখব।

                          +
                          interface FileInterface
                          +{
                          +    public function content();
                          +}
                          +
                          +class RealFile implements FileInterface
                          +{
                          +    private $fileName;
                          +
                          +    private $fileContent;
                          +
                          +    public function __construct($fileName)
                          +    {
                          +        $this->fileName = $fileName;
                          +
                          +        $this->readFile();
                          +    }
                          +
                          +    private function readFile()
                          +    {
                          +        $this->fileContent = file_get_contents($this->fileName);
                          +    }
                          +
                          +    public function content()
                          +    {
                          +        return $this->fileContent;
                          +    }
                          +}
                          +
                          +class ProxyFile implements FileInterface
                          +{
                          +    private $fileName;
                          +
                          +    private $realFileObject;
                          +
                          +    public function __construct($fileName)
                          +    {
                          +        $this->fileName = $fileName;
                          +    }
                          +
                          +    public function content()
                          +    {
                          +        // Lazy load the file using the RealFile class
                          +        if (!$this->realFileObject) {
                          +            $this->realFileObject = new RealFile($this->fileName);
                          +        }
                          +
                          +        return $this->realFileObject->content();
                          +    }
                          +}
                          +
                          +

                          উপরের কোডটি খেয়াল করলে আমরা দেখতে পাব একই ইন্টারফেইস FileInterface ব্যাবহার করে রিয়েল অবজেক্ট এর জন্য RealFile ও প্রক্সি অবজেক্টের জন্য ProxyFile নামক ক্লাস ইমপ্লিমেন্ট করা হয়েছে।

                          +

                          ProxyFile এর content() মেথডটি দেখলে বুঝতে পাব যে এর মাধ্যমে মুল RealFile ক্লাস এর ইন্সটানশিয়েট করা হয়েছে লেজিলোডিং পদ্ধতির মাধ্যমে যাতে অ্যাকসেস না করা পর্যন্ত ইন্সটানশিয়েট না করা হয়।

                          +
                          public function content()
                          +{
                          +    // Lazy load the file using the RealFile class
                          +    if (!$this->realFileObject) {
                          +        $this->realFileObject = new RealFile($this->fileName);
                          +    }
                          +
                          +    return $this->realFileObject->content();
                          +}
                          +
                          +

                          এবার নিচের মত করে উভয় ক্লাসকে ইন্সটানশিয়েট করে কল করা হলে প্রথমে ভিন্ন ভিন্ন মেমোরি দখল করবে।

                          +
                          $realFile = new RealFile('/path/to/file.jpg');
                          +var_dump(memory_get_usage()); // ~5Mb
                          +$realFile->content();
                          +var_dump(memory_get_usage()); // ~5Mb
                          +
                          +$realFile->content();
                          +var_dump(memory_get_usage()); // ~5Mb
                          +
                          +$proxyFile = new ProxyFile('/path/to/file.jpg');
                          +var_dump(memory_get_usage()); // ~350Kb
                          +$proxyFile->content();
                          +var_dump(memory_get_usage()); // ~5Mb
                          +
                          +$proxyFile->content();
                          +var_dump(memory_get_usage()); // ~5Mb
                          +
                          +

                          এই চ্যাপ্টারের সোর্স কোডটি এই লিঙ্ক থেকে পাবেন।

                          + + +
                          + +
                          +
                          +
                          + +

                          results matching ""

                          +
                            + +
                            +
                            + +

                            No results matching ""

                            + +
                            +
                            +
                            + +
                            +
                            + +
                            + + + + + + + + + + + + + + +
                            + + +
                            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/singleton-pattern.html b/_book/design-patterns/singleton-pattern.html new file mode 100644 index 0000000..3e09d24 --- /dev/null +++ b/_book/design-patterns/singleton-pattern.html @@ -0,0 +1,766 @@ + + + + + + সিঙ্গেলটোন · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                            +
                            + + + + + + + + +
                            + +
                            + +
                            + + + + + + + + +
                            +
                            + +
                            +
                            + +
                            + +

                            সিঙ্গেলটোন

                            +

                            সিঙ্গেলটোন ডিজাইন প্যাটার্ন ক্রিয়েশনাল ডিজাইন প্যাটার্ন ক্যাটাগরির মধ্যে পরে। এই প্যাটার্নের মুল উদ্দেশ্য হল প্রতিটি ক্লাসের শুধু মাত্র একটিই ইন্সট্যান্স/অবজেক্ট থাকা।

                            +

                            ধরুন, Singleton নামে আমাদের একটা ফাইনাল ক্লাস আছে তাহলে সিঙ্গেলটোন প্যাটার্নে এই ক্লাসকে এমনভাবে ব্যবহার করতে হবে যেন নতুন কোন ইন্সট্যান্স/অবজেক্ট তৈরি না হয়ে একটিই থাকে আর ক্লাসটিকে ইনহেরিট ও করা না যায়, যা আমরা নিচের মত করে করতে পারিঃ

                            +
                            <?php
                            +
                            +final class Singleton
                            +{
                            +    private static $instance;
                            +
                            +    public static function getInstance()
                            +    {
                            +        if (null === self::$instance) {
                            +            self::$instance = new self();
                            +        }
                            +
                            +        return self::$instance;
                            +    }
                            +
                            +    private function __construct()
                            +    {
                            +
                            +    }
                            +
                            +    private function __clone()
                            +    {
                            +
                            +    }
                            +
                            +    private function __wakeup()
                            +    {
                            +
                            +    }
                            +
                            +    public function sayHi()
                            +    {
                            +        echo 'Hi';
                            +    }
                            +}
                            +
                            +$singleton = Singleton::getInstance();
                            +
                            +$singleton->sayHi();
                            +
                            +

                            এখানে ক্লাসটি বাইরে থেকে ইন্সট্যান্সিয়েট না করে getInstance() স্ট্যাটিক মেথডটি ডিক্লেয়ার করা হয়েছে যাতে ক্লাসের ইন্সট্যান্সটা রিটার্ন করে।

                            +

                            অর্থাৎ,

                            +
                            $singleton = new Singleton();
                            +
                            +

                            এর পরিবর্তে

                            +
                            $singleton = Singleton::getInstance();
                            +
                            +

                            ব্যবহার করা হয়েছে।

                            +

                            আর ক্লাসের ইন্সট্যান্স $instance নামে ভ্যারিয়েবল এ রাখা হয়েছে।

                            +

                            যেমনঃ

                            +
                            private static $instance;
                            +
                            +public static function getInstance()
                            +{
                            +    if (null === self::$instance) {
                            +        self::$instance = new self();
                            +    }
                            +
                            +    return self::$instance;
                            +}
                            +
                            +

                            আবার ক্লাসের একাধিক ইন্সস্ট্যান্স তৈরিতে বাধা দিতে আমরা __clone()__wakeup() ম্যাজিক মেথডগুলি ব্যাবহার করেছি।

                            +

                            এই লিঙ্ক থেকে কোডটি পাবেন।

                            + + +
                            + +
                            +
                            +
                            + +

                            results matching ""

                            +
                              + +
                              +
                              + +

                              No results matching ""

                              + +
                              +
                              +
                              + +
                              +
                              + +
                              + + + + + + + + + + + + + + +
                              + + +
                              + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/design-patterns/strategy-pattern.html b/_book/design-patterns/strategy-pattern.html new file mode 100644 index 0000000..e54ff8c --- /dev/null +++ b/_book/design-patterns/strategy-pattern.html @@ -0,0 +1,758 @@ + + + + + + স্ট্রাটেজি · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                              +
                              + + + + + + + + +
                              + +
                              + +
                              + + + + + + + + +
                              +
                              + +
                              +
                              + +
                              + +

                              স্ট্রাটেজি

                              +

                              Strategy ডিজাইন প্যাটার্ন বিহেভিওরাল ডিজাইন প্যাটার্নের মধ্যে পরে। Strategy এর অর্থ হল কৌশল, কোন কিছু করতে গেলে তার জন্য কৌশল কিংবা এক গুচ্ছ পদক্ষেপ গ্রহণ করাই হল স্ট্রাটেজি।

                              +

                              প্রোগ্রামিং এর পরিভাষায়, একটি নির্দিষ্ট কাজ সম্পন্ন করতে ভিন্ন ভিন্ন অ্যালগরিদম নির্ধারণ করার স্বাধীনতা থাকাই স্ট্রাটেজি প্যাটার্ন। এই প্যটার্নকে আবার পলিসি প্যাটার্নও বলা হয়ে থাকে।

                              +

                              ধরুন, আপনি ঢাকা থেকে চট্টগ্রাম যাইতে চাচ্ছেন এরজন্য আপনি চাইলে বাস, ট্রেন কিংবা প্লেন এ করে যাইতে পারেন। এইক্ষেত্রে গন্তব্যস্থল একটিই কিন্তু এটা সম্পন্ন করতে ভিন্ন ভিন্ন স্ট্রাটেজি অনুসরণ করা যায়।

                              +

                              এবার চলুন একটা বাস্তব ভিত্তিক উদাহরণের মাধ্যমে প্যাটার্নটি বুঝা যাক। প্রথমে চলুন একটা ইন্টারফেইস বানিয়ে ভিন্ন ভিন্ন স্ট্রাটেজি ইমপ্লিমেন্ট করি নিচের মত করে।

                              +
                              interface TravelStrategy
                              +{
                              +    public function travel();
                              +}
                              +
                              +class BusTravelStrategy implements TravelStrategy
                              +{
                              +    public function travel()
                              +    {
                              +        // Bus travel strategy will goes here
                              +    }
                              +}
                              +
                              +class TrainTravelStrategy implements TravelStrategy
                              +{
                              +    public function travel()
                              +    {
                              +        // Train travel strategy will goes here
                              +    }
                              +}
                              +
                              +class PlaneTravelStrategy implements TravelStrategy
                              +{
                              +    public function travel()
                              +    {
                              +        // Plane travel strategy will goes here
                              +    }
                              +}
                              +
                              +

                              এবার মেইন কনটেক্সট ক্লাস হিসেবে Traveler নামক একটা ক্লাস ডিফাইন করি।

                              +
                              class Traveler
                              +{
                              +    protected $traveler;
                              +
                              +    public function __construct(TravelStrategy $traveler)
                              +    {
                              +        $this->traveler = $traveler;
                              +    }
                              +
                              +    public function travel()
                              +    {
                              +        $this->traveler->travel();
                              +    }
                              +}
                              +
                              +

                              পরিশেষে, স্ট্রাটেজি পরিবর্তন করে সহজে আমরা আমাদের কার্য সম্পন্ন করতে পারি।

                              +
                              $traveler = new Traveler(new BusTravelStrategy());
                              +$traveler->travel();
                              +
                              +$traveler1 = new Traveler(new PlaneTravelStrategy());
                              +$traveler1->travel();
                              +
                              +

                              এই চ্যাপ্টারের সোর্স কোডটি এই লিঙ্ক থেকে পাবেন।

                              + + +
                              + +
                              +
                              +
                              + +

                              results matching ""

                              +
                                + +
                                +
                                + +

                                No results matching ""

                                + +
                                +
                                +
                                + +
                                +
                                + +
                                + + + + + + + + + + + + + + +
                                + + +
                                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/facade-pattern.md b/_book/facade-pattern.md new file mode 100644 index 0000000..41d9284 --- /dev/null +++ b/_book/facade-pattern.md @@ -0,0 +1,175 @@ +# ফ্যাসাড ডিজাইন প্যাটার্নঃ + +```Facade``` ডিজাইন প্যাটার্ন স্ট্রাকচারাল ডিজাইন প্যাটার্নের মধ্যে পরে। +ফ্যাসাড ডিজাইন প্যাটার্ন এর কাজ হল ক্লায়েন্ট এর কাছে একটা কমপ্লেক্স সিস্টেম বা ইন্টারফেইস হতে একটা সহজ ইন্টারফেইস প্রদান করা যাতে কমপ্লেক্স কিংবা আগলি কোড গুলো হিডেন অবস্থায় থাকে। + +লেগাসি কিংবা কমপ্লেক্স কোন সিস্টেম এর কোডকে সহজ ভাবে উপস্থাপন করার দরকার হলে এই প্যাটার্ন ব্যাবহার করা হয়। + +ধরুন আপনার সিস্টেম কিংবা অ্যাপ্লিকেশনে একটা কমপ্লেক্স লাইব্রেরি ব্যাবহার করার দরকার পরতেছে আর আপনি উক্ত কমপ্লেক্স পার্টকে সহজ করে তোলার জন্য একটা ```Wrapper``` বানিয়ে সেইটা করতে পারেন। + +এবার নিচে একটা উদাহরণের মাধ্যমে প্যাটার্নটি বোঝানোর চেষ্টা করা হলঃ + +```php +cart = new Cart; + $this->order = new Order; + $this->payment = new Payment; + $this->shipping = new Shipping; + } + + public function addToCart($products) + { + $this->cart->addProducts($products); + } + + public function checkout() + { + $products = $this->cart->getProducts(); + + $this->totalAmount = $this->order->process($products); + } + + public function makePayment() + { + $charge = $this->shipping->calculateCharge(); + $this->payment->charge($charge); + + $isCompleted = $this->payment->makePayment(); + + if ($isCompleted) { + $this->shipping->shipProducts(); + } + } +} + +$customer = new CustomerFacade; + +$products = [ + [ + 'name' => 'Polo T-Shirt', + 'price' => 40, + ], + [ + 'name' => 'Smart Watch', + 'price' => 400, + ], +]; + +$customer->addToCart($products); +$customer->checkout(); +$customer->makePayment(); +``` + +উপরের কোডটি খেয়াল করলে দেখতে পারবেন এখানে একটা ই-কমার্স অ্যাপ্লিকেশনের প্রসেস দেখানো হয়েছে। +এর জন্য আমরা যথাক্রমে ```Cart```, ```Order```, ```Payment```, ```Shipping``` ক্লাসগুলো ব্যাবহার করেছি আর ফ্যাসাড হিসেবে ```CustomerFacade``` ক্লাস ব্যাবহার করেছি। +এখানে কোন প্রোডাক্টকে কার্টে যুক্ত করার জন্য ```Cart``` ক্লাসটি, অর্ডার প্রসেস করার জন্য ```Order``` ক্লাসটি, পেমেন্ট প্রসেস করার জন্য ```Payment``` ক্লাসটি আর প্রডাক্ট এর শিপিং হ্যান্ডল করার জন্য ```Shipping``` ক্লাসটি ব্যাবহার করেছি। + +এখন মুল কথা হল আমরা যদি এসব কাজের জন্য প্রতিবার উক্ত ক্লাস গুলোকে বার বার কল করি তাহলে অনেক সময় সাপেক্ষ বেপার হয়ে পরবে আর স্ট্রাকচারটিও ভাল হবেনা। আর তাই এখানে ফ্যাসাড প্যাটার্নটি ব্যাবহার করা হয়েছে। যাতে ডেভেলপার কিংবা ক্লায়েন্ট হিসেবে সুধু মাত্র ```CustomerFacade``` ক্লাসটিকে ব্যাবহার করে উপরে উল্লেখিত সবগুলো কাজ অনায়াসে করা সম্ভব। + + +## অতিরিক্ত বিষয় (লারাভেল ফ্যাসাড) ঃ +আমরা যারা লারাভেল ব্যাবহার করি তারা কম বেশি সবাই জানি লারাভেল এ অনেকগুলো বিল্ড-ইন ফ্যাসাড আছে কিংবা ব্যাবহার হয়। যেমনঃ ```DB```, ```View```, ```Event```, ```Queue```, ```Mail``` ইত্যাদি। + +আমরা মূলত যেটা জানি তা হল লারাভেল এ ফ্যাসাড ```Statically``` কোন ক্লাসকে কল করার জন্য ব্যাবহার হয়। আসলে বিষয়টি ঠিক তেমন নয়। +এখানে অনেক কমপ্লেক্স সিস্টেমকে হাইড করে আমাদের কাছে সহজ ভাবে উপস্থাপন করা হয়েছে তার সাথে লারাভেল ফ্যাসাড প্যাটার্নের সাথে ```__callStatic``` ম্যাজিক মেথডটি ব্যাবহার করা হয়েছে। +যাতে ডেভেলপার কিংবা ক্লায়েন্টকে আলাদাভাবে ক্লাস ইন্সট্যানশিয়েট করতে না হয়। + +নিচে একটা উদাহরণ দেয়া হলঃ + +```php +$method(); + case 1: + return $instance->$method($args[0]); + case 2: + return $instance->$method($args[0], $args[1]); + case 3: + return $instance->$method($args[0], $args[1], $args[2]); + case 4: + return $instance->$method($args[0], $args[1], $args[2], $args[3]); + default: + return call_user_func_array([$instance, $method], $args); + } + + } +} + +var_dump(PersonFacade::getFullName()); +``` + +এই চ্যাপ্টারের সোর্স কোডটি [এই লিঙ্ক](https://github.com/sohelamin/php-design-patterns) থেকে পাবেন। diff --git a/_book/factory-pattern.md b/_book/factory-pattern.md new file mode 100644 index 0000000..36a0858 --- /dev/null +++ b/_book/factory-pattern.md @@ -0,0 +1,514 @@ +# ফ্যাক্টরী ডিজাইন প্যাটার্নঃ + +ফ্যাক্টরী প্যাটার্ন এমন একটি প্যাটার্ন যা কম বেশি সব ধরনের অ্যাপ্লিকেশনে ব্যাবহৃত হয়ে থাকে এইটা ক্রিয়েশনাল প্যাটার্ন ক্যাটাগরীর মধ্যে পরে। + +ফ্যাক্টরী প্যাটার্নের মূল উদ্দেশ্যই হল এর প্রোডাক্ট কিংবা চাইল্ড ক্লাসের অবজেক্ট তৈরি করে দেয়া। যেমন বাস্তব জীবনে যেভাবে ফ্যাক্টরীতে প্রোডাক্ট তৈরি হয়ে থাকে। + +এই প্যাটার্ন ক্লাইন্টের কাছে অবজেক্ট ইনস্টানশিয়েট করার লজিক অদৃশ্যমান রাখে। আর অবজেক্টের ক্লাস গুলা একটা কমন ইন্টারফেইস কে ফলো করে বানানো থাকে। + +এই প্যাটার্ন সাধারণত ৩ প্রকারেরঃ +১. সিম্পল ফ্যাক্টরী। +২. ফ্যাক্টরী মেথড। +৩. অ্যাবস্ট্রাক্ট ফ্যাক্টরী। + +## ১. সিম্পল ফ্যাক্টরীঃ +ফ্যাক্টরী প্যাটার্নের মধ্যে সিম্পল ফ্যাক্টরী হচ্ছে সবচেয়ে সহজ প্যাটার্ন যদিও অফিশিয়ালি এই প্যাটার্ন ডিজাইন প্যাটার্ন হিসেবে স্বীকৃত না। + +এই প্যাটার্নের নিয়ম মতে এর একটি ফ্যাক্টরী থাকবে আর একটি ফ্যাক্টরী একই সময় শুধুমাত্র একটাই প্রোডাক্ট তৈরি করবে অর্থাৎ একটিই ইনস্টান্স কিংবা অবজেক্ট রিটার্ন করবে। + +নিচে একটা উদাহরণ দেয়া হলঃ + +```php +class CarFactory +{ + protected $brands = []; + + public function __construct() + { + $this->brands = [ + 'mercedes' => 'MercedesCar', + 'toyota' => 'ToyotaCar', + ]; + } + + public function make($brand) + { + if (!array_key_exists($brand, $this->brands)) { + return new Exception('Not available this car'); + } + + $className = $this->brands[$brand]; + + return new $className(); + } +} + +interface CarInterface +{ + public function design(); + public function assemble(); + public function paint(); +} + +class MercedesCar implements CarInterface +{ + public function design() + { + return 'Designing Mercedes Car'; + } + + public function assemble() + { + return 'Assembling Mercedes Car'; + } + + public function paint() + { + return 'Painting Mercedes Car'; + } +} + +class ToyotaCar implements CarInterface +{ + public function design() + { + return 'Designing Toyota Car'; + } + + public function assemble() + { + return 'Assembling Toyota Car'; + } + + public function paint() + { + return 'Painting Toyota Car'; + } +} + +$carFactory = new CarFactory; + +$mercedes = $carFactory->make('mercedes'); +echo $mercedes->design() . '
                                '; +echo $mercedes->assemble() . '
                                '; +echo $mercedes->paint() . '
                                '; + +echo '
                                '; + +$toyota = $carFactory->make('toyota'); +echo $toyota->design() . '
                                '; +echo $toyota->assemble() . '
                                '; +echo $toyota->paint() . '
                                '; +``` + +এখানে ```CarFactory``` নামে মূল ফ্যাক্টরী ক্লাস ডিফাইন করা হয়েছে যেটির মাধ্যমে একটা ```Car``` ইনস্টান্স তৈরি করা হবে। +```Car``` এর জন্য ২ টি ক্লাস যথাক্রমে ```MercedesCar``` ও ```ToyotaCar``` ডিফাইন করা হয়েছে যেগুলো ```CarInterface``` কে ফলো করেছে। + +এবার চলুন ```CarFactory``` ক্লাসটিকে ইনস্টানশিয়েট করি। + +```php +$carFactory = new CarFactory; +``` + +এরপর ধরুন ```MercedesCar``` ক্লাসকে ফ্যাক্টরির মাধ্যমে ইনস্টানশিয়েট করব তাহলে টাইপ/প্যারামিটার হিসেবে ```mercedes``` দিতে হবে নিচের মত করে। + +```php +$mercedes = $carFactory->make('mercedes'); +echo $mercedes->design() . '
                                '; +echo $mercedes->assemble() . '
                                '; +echo $mercedes->paint() . '
                                '; +``` + +অনুরূপ ভাবে ```ToyotaCar``` ক্লাসকে ইনস্টানশিয়েট করতে হলে + +```php +$toyota = $carFactory->make('toyota'); +echo $toyota->design() . '
                                '; +echo $toyota->assemble() . '
                                '; +echo $toyota->paint() . ‘
                                '; +``` + +আর ডিফাইন না করা কোন ক্লাসের টাইপ দিলে সেটি এরর দেখাবে। + +## ২. ফ্যাক্টরী মেথডঃ + +ফ্যাক্টরী মেথড প্যাটার্ন অনেকখানি সিম্পল ফ্যাক্টরী প্যাটার্নের মতই শুধুমাত্র এর মূল পার্থক্য হল এটি তার সাব ক্লাস গুলোকে ক্লাস ইনস্টানশিয়েট করার স্বাধীনতা দিয়ে দেয়। আর এর একাধিক ফ্যাক্টরী থাকতে পারে। + +নিচে একটা উদাহরণ দেয়া হলঃ + +```php +abstract class VehicleFactoryMethod +{ + abstract public function make($brand); +} + +class CarFactory extends VehicleFactoryMethod +{ + public function make($brand) + { + $car = null; + + switch ($brand) { + case "mercedes": + $car = new MercedesCar; + break; + case "toyota": + $car = new ToyotaCar; + break; + } + + return $car; + } +} + +class BikeFactory extends VehicleFactoryMethod +{ + public function make($brand) + { + $bike = null; + + switch ($brand) { + case "yamaha": + $bike = new YamahaBike; + break; + case "ducati": + $bike = new DucatiBike; + break; + } + + return $bike; + } +} + +interface CarInterface +{ + public function design(); + + public function assemble(); + + public function paint(); +} + +interface BikeInterface +{ + public function design(); + + public function assemble(); + + public function paint(); +} + +class MercedesCar implements CarInterface +{ + public function design() + { + return 'Designing Mercedes Car'; + } + + public function assemble() + { + return 'Assembling Mercedes Car'; + } + + public function paint() + { + return 'Painting Mercedes Car'; + } +} + +class ToyotaCar implements CarInterface +{ + public function design() + { + return 'Designing Toyota Car'; + } + + public function assemble() + { + return 'Assembling Toyota Car'; + } + + public function paint() + { + return 'Painting Toyota Car'; + } +} + +class YamahaBike implements BikeInterface +{ + public function design() + { + return 'Designing Yamaha Bike'; + } + + public function assemble() + { + return 'Assembling Yamaha Bike'; + } + + public function paint() + { + return 'Painting Yamaha Bike'; + } +} + +class DucatiBike implements BikeInterface +{ + public function design() + { + return 'Designing Ducati Bike'; + } + + public function assemble() + { + return 'Assembling Ducati Bike'; + } + + public function paint() + { + return 'Painting Ducati Bike'; + } +} + +$carFactoryInstance = new CarFactory; + +$mercedes = $carFactoryInstance->make('mercedes'); +echo $mercedes->design() . '
                                '; +echo $mercedes->assemble() . '
                                '; +echo $mercedes->paint() . '
                                '; + +echo '
                                '; + +$toyota = $carFactoryInstance->make('toyota'); +echo $toyota->design() . '
                                '; +echo $toyota->assemble() . '
                                '; +echo $toyota->paint() . '
                                '; + +echo '
                                '; + +$bikeFactoryInstance = new BikeFactory; + +$yamaha = $bikeFactoryInstance->make('yamaha'); +echo $yamaha->design() . '
                                '; +echo $yamaha->assemble() . '
                                '; +echo $yamaha->paint() . '
                                '; + +echo '
                                '; + +$ducati = $bikeFactoryInstance->make('ducati'); +echo $ducati->design() . '
                                '; +echo $ducati->assemble() . '
                                '; +echo $ducati->paint() . '
                                '; +``` + +এখানে ফ্যাক্টরী মেথডের জন্য ```VehicleFactoryMethod``` নামে একটা অ্যাবস্ট্রাক্ট ক্লাস ডিফাইন করা হয়েছে যেটির সাব ক্লাস যথাক্রমে ```CarFactory``` ও ```BikeFactory``` আছে যেগুলা ভিন্ন ভিন্ন একক ফ্যাক্টরী। +আবার প্রতিটি ফ্যাক্টরীর জন্য সিম্পল ফ্যাক্টরী প্যাটার্নের ন্যায় ইন্টারফেইস ```CarInterface``` ও ```BikeInterface``` ডিফাইন করা হয়েছে যেগুলোকে ইমপ্লিমেন্ট করে কংক্রিট ক্লাস অর্থাৎ ইনস্টানশিয়েট যোগ্য ক্লাস যথাক্রমে ```CarFactory``` এর আওতায় ```MercedesCar``` ও ```ToyotaCar``` এবং ```BikeFactory``` এর আওতায় ```YamahaBike``` ও ```DucatiBike``` ডিফাইন করা হয়েছে। + +সুতরাং ```CarFactory``` ও ```BikeFactory``` ক্লাসগুলো নির্ধারণ করতে পারবে সে কোন ক্লাসকে ইনস্টানশিয়েট করবে। + +নিচের কোডটি খেয়াল করলে বুঝতে পারবেন ২ টি আলাদা ফ্যাক্টরীর মাধ্যমে প্যারামিটার কিংবা ```Car``` এর ব্র্যান্ড পাস করে কাঙ্ক্ষিত অবজেক্ট কে পাওয়া যায়। + +```php +$carFactoryInstance = new CarFactory; + +$mercedes = $carFactoryInstance->make('mercedes'); +echo $mercedes->design() . '
                                '; +echo $mercedes->assemble() . '
                                '; +echo $mercedes->paint() . '
                                '; + +echo '
                                '; + +$toyota = $carFactoryInstance->make('toyota'); +echo $toyota->design() . '
                                '; +echo $toyota->assemble() . '
                                '; +echo $toyota->paint() . '
                                '; + +echo '
                                '; + +$bikeFactoryInstance = new BikeFactory; + +$yamaha = $bikeFactoryInstance->make('yamaha'); +echo $yamaha->design() . '
                                '; +echo $yamaha->assemble() . '
                                '; +echo $yamaha->paint() . '
                                '; + +echo '
                                '; + +$ducati = $bikeFactoryInstance->make('ducati'); +echo $ducati->design() . '
                                '; +echo $ducati->assemble() . '
                                '; +echo $ducati->paint() . ‘
                                '; +``` + +## ৩. অ্যাবস্ট্রাক্ট ফ্যাক্টরীঃ + +অ্যাবস্ট্রাক্ট ফ্যাক্টরী এমন একটি পদ্ধতি প্রদান করে যেখানে একটি মূল (অ্যাবস্ট্রাক্ট) ফ্যাক্টরী অনেকগুলো একক ফ্যাক্টরীকে একত্রিত করে রাখে। + +এক কথায়, প্রথমে একটি অ্যাবস্ট্রাক্ট ফ্যাক্টরী অনেকগুলো প্রোডাক্ট ফ্যাক্টরী তৈরি করে এরপর প্রতিটি ফ্যাক্টরী একাধিক প্রোডাক্ট কিংবা অবজেক্ট তৈরি করে। + +উল্লেখ্য, প্রতিটি প্রোডাক্ট ফ্যাক্টরী ক্লাসকে একটা কমন অ্যাবস্ট্রাক্ট ক্লাসকে এক্সটেন্ড করতে হবে অথবা একটা কমন ইন্টারফেইসকে ইমপ্লিমেন্ট করতে হবে। +আবার প্রতিটি প্রোডাক্ট ফ্যাক্টরী ক্লাসে একাধিক আর একই মেথড থাকতে হবে। + +নিচে একটা উদাহরণ দেয়া হলঃ + +```php +abstract class AbstractVehicleFactory +{ + abstract public function makeCar(); + abstract public function makeBike(); +} + +class BangladeshiFactory extends AbstractVehicleFactory +{ + public function makeCar() + { + return new ToyotaCar(); + } + + public function makeBike() + { + return new YamahaBike(); + } +} + +class USAFactory extends AbstractVehicleFactory +{ + public function makeCar() + { + return new MercedesCar(); + } + + public function makeBike() + { + return new DucatiBike(); + } +} + +abstract class AbstractVehicle +{ + abstract public function design(); + abstract public function assemble(); + abstract public function paint(); +} + +abstract class AbstractCarVehicle extends AbstractVehicle +{ + +} + +abstract class AbstractBikeVehicle extends AbstractVehicle +{ + +} + +class MercedesCar extends AbstractCarVehicle +{ + public function design() + { + return 'Designing Mercedes Car'; + } + + public function assemble() + { + return 'Assembling Mercedes Car'; + } + + public function paint() + { + return 'Painting Mercedes Car'; + } +} + +class ToyotaCar extends AbstractCarVehicle +{ + public function design() + { + return 'Designing Toyota Car'; + } + + public function assemble() + { + return 'Assembling Toyota Car'; + } + + public function paint() + { + return 'Painting Toyota Car'; + } +} + +class YamahaBike extends AbstractBikeVehicle +{ + public function design() + { + return 'Designing Yamaha Bike'; + } + + public function assemble() + { + return 'Assembling Yamaha Bike'; + } + + public function paint() + { + return 'Painting Yamaha Bike'; + } +} + +class DucatiBike extends AbstractBikeVehicle +{ + public function design() + { + return 'Designing Ducati Bike'; + } + + public function assemble() + { + return 'Assembling Ducati Bike'; + } + + public function paint() + { + return 'Painting Ducati Bike'; + } +} + +$bangladeshiFactoryInstance = new BangladeshiFactory; +$car = $bangladeshiFactoryInstance->makeCar(); +echo $car->design() . '
                                '; +echo $car->assemble() . '
                                '; +echo $car->paint() . '
                                '; + +echo '
                                '; + +$bike = $bangladeshiFactoryInstance->makeBike(); +echo $bike->design() . '
                                '; +echo $bike->assemble() . '
                                '; +echo $bike->paint() . '
                                '; + +echo '
                                '; + +$usaFactoryInstance = new USAFactory; +$car = $usaFactoryInstance->makeCar(); +echo $car->design() . '
                                '; +echo $car->assemble() . '
                                '; +echo $car->paint() . '
                                '; + +echo '
                                '; + +$bike = $usaFactoryInstance->makeBike(); +echo $bike->design() . '
                                '; +echo $bike->assemble() . '
                                '; +echo $bike->paint() . ‘
                                '; +``` + +উপরের কোডে ```AbstractVehicleFactory``` নামে একটা অ্যাবস্ট্রাক্ট ফ্যাক্টরী ক্লাস ডিফাইন করা হয়েছে যেখানে ```makeCar()``` ও ```makeBike()``` ২টা মেথড দেয়া আছে যাতে সাব ফ্যাক্টরী গুলো ওই মেথড গুলো ডিফাইন করে। + +এখানে একটি মেথড ```Car``` অবজেক্ট তৈরি করতে আরেকটি ```Bike``` অবজেক্ট তৈরি করতে ব্যবহৃত হয়েছে যা সব গুলা ফ্যাক্টরীকেই করতে হবে। +আর মূল বিষয় হল একেক ফ্যাক্টরী একেক ব্র্যান্ডের ```Car``` ও ```Bike``` অবজেক্ট তৈরি করবে। + +যেমন এখানে আমরা ```BangladeshiFactory``` ফ্যাক্টরী ব্যাবহার করেছি যেটি ```ToyotaCar``` ও ```YamahaBike``` ক্লাসের অবজেক্ট তৈরি করবে। অনুরূপ ভাবে, ```USAFactory``` ফ্যাক্টরী ```MercedesCar``` ও ```DucatiBike``` ক্লাসের অবজেক্ট তৈরি করবে। + +আবার আপনি চাইলে একটা ফ্যাক্টরীতে একাধিক ব্রান্ডের ```Car``` কিংবা ```Bike``` এর অবজেক্ট তৈরি করতে পারেন সেক্ষেত্রে র‍্যান্ডমলি কিংবা লজিক্যালি করতে হবে। + +এই [লিঙ্ক](https://github.com/sohelamin/php-design-patterns) থেকে সোর্স কোডটি পাবেন। \ No newline at end of file diff --git a/_book/filesystem.html b/_book/filesystem.html new file mode 100644 index 0000000..d4d9617 --- /dev/null +++ b/_book/filesystem.html @@ -0,0 +1,766 @@ + + + + + + ফাইলসিস্টেম · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                +
                                + + + + + + + + +
                                + +
                                + +
                                + + + + + + + + +
                                +
                                + +
                                +
                                + +
                                + +

                                ফাইলসিস্টেম

                                +

                                এই চ্যাপ্টারে আমরা পিএইচপির ডিরেক্টরী এবং ফাইল সম্পর্কিত কিছু ব্যাসিক অপারেশন দেখবো । এখানে দেখানো পদ্ধতি ছাড়াও আরো নানা পদ্ধতিতে একই কাজ করা যেতে পারে । আপাতত আমরা একটি করে পদ্ধতি দেখবো । পরবর্তীতে আমরা আরো এ্যাডভান্সড ব্যবহার দেখবো ।

                                +

                                ডিরেক্টরী তৈরি করা

                                +

                                আমরা নতুন একটি ডিরেক্টরী বা ফোল্ডার তৈরি করতে পারি mkdir ফাংশনটি ব্যবহার করে ।

                                +
                                <?php
                                +$success = mkdir("test_dir", 0755);
                                +var_dump($success);
                                +
                                +

                                এখানে আমরা আমাদের কারেন্ট লোকেশনে test_dir নামে একটি ডিরেক্টরী তৈরি করেছি যেটার পার্মিশন লেভেল - 0755 । পার্মিশন সম্পর্কে আরো বিস্তারিত জানতে লিনাক্স ফাইল পার্মিশন এর উপর গুগলে সার্চ করতে পারেন ।

                                +

                                এই ফাংশনটি ৩য় আরেকটি বুলিয়ান আর্গুমেন্ট নেয় - যদি আমরা চাই নেস্টেড ডিরেক্টরী তৈরি করতে (যেমন: "my_dir/sub_dir/another_dir") তাহলে এই প্যারামিটার এর জন্য আমরা true পাস করবো । অন্যথায় পিএইচপি এরর থ্রো করবে ।

                                +
                                <?php
                                +$success = mkdir("my_dir/sub_dir/another_dir", 0755, true);
                                +var_dump($success);
                                +
                                +

                                ডিরেক্টরী ব্রাউজ করা

                                +

                                আমরা কোন ডিরেক্টরী এর কন্টেন্ট ব্রাউজ করার জন্য scandir ফাংশনটি ব্যবহার করতে পারি ।

                                +
                                <?php
                                +$dir    = '/tmp';
                                +$files1 = scandir($dir);
                                +$files2 = scandir($dir, SCANDIR_SORT_NONE);
                                +
                                +print_r($files1);
                                +print_r($files2);
                                +
                                +

                                এই ফাংশনটির প্রথম প্যারামিটার ফাইল পাথ এ্যাক্সেপ্ট করে । যেই ডিরেক্টরীর কন্টেন্ট আমরা ব্রাউজ করতে চাই সেটির পাথ আমরা এই আর্গুমেন্ট হিসেবে পাস করবো । ২য় প্যারামিটারটি আমরা সর্টিং এর জন্য ব্যবহার করি । এটির ভ্যালু হিসেবে আমরা এই ৩টি কন্সট্যান্ট এর যে কোনটি পাস করতে পারি:

                                +
                                  +
                                • SCANDIR_SORT_ASCENDING
                                • +
                                • SCANDIR_SORT_DESCENDING
                                • +
                                • SCANDIR_SORT_NONE
                                • +
                                +

                                এই প্যারামিটারটির জন্য ডিফল্ট ভ্যালু হিসেবে SCANDIR_SORT_ASCENDING থাকে ।

                                +

                                ডিরেক্টরী ডিলিট করা

                                +

                                rmdir ফাংশনটি ব্যবহার করে আমরা কোন ডিরেক্টরী ডিলিট করতে পারি:

                                +
                                <?php
                                +rmdir('examples');
                                +
                                +

                                তবে ডিরেক্টরী ডিলিট করার আগে নিশ্চিত হতে হবে যে এই ডিরেক্টরীটি ফাকা আছে কিনা । যদি এটির মধ্যে অন্য কোন ফাইল বা সাব ডিরেক্টরী থাকে তবে আগে সেগুলো ডিলিট করে নিতে হবে ।

                                +

                                ফাইল তৈরি করা / ফাইলে কন্টেন্ট যোগ করা

                                +

                                file_put_contents ফাংশনটি ব্যবহার করে আমরা একটি ফাইলের কন্টেন্ট ওভাররাইট করতে পারি । যদি ঐ ফাইলটি আগে থেকে তৈরি করা না থাকে তাহলে ফাংশনটি ফাইলটি তৈরি করে নেয় ।

                                +
                                <?php
                                +$file = 'people.txt';
                                +$text = "Abu Ashraf Masnun\n";
                                +file_put_contents($file, $text);
                                +
                                +

                                ডিফল্টভাবে পিএইচপি ফাইলের কন্টেন্ট ওভাররাইট করে, অর্থাৎ আগের সব কিছু মুছে ফেলে নতুন করে কন্টেন্ট যোগ করে । আমরা যদি চাই আগের কন্টেন্টের সাথে অতিরিক্ত নতুন কন্টেন্ট যোগ করতে তাহলে আমরা ৩য় আর্গুমেন্ট হিসেবে FILE_APPEND কন্সট্যান্টটি পাস করবো । যেমন:

                                +
                                <?php
                                +$file = 'people.txt';
                                +$text = "The Doctor\n";
                                +file_put_contents($file, $text, FILE_APPEND);
                                +
                                +

                                এবার যদি আমরা ফাইলটি খুলি তাহলে দেখবো আমাদের আগের কন্টেন্ট এর সাথে এই নতুন টেক্সট যোগ হয়েছে ।

                                +

                                ফাইল পড়া

                                +

                                file_get_contents ফাংশনটিতে কোন ফাইল পাথ পাস করলে এটি ঐ ফাইলের কন্টেন্ট রিটার্ন করবে ।

                                +
                                <?php
                                +$file = file_get_contents('./people.txt');
                                +
                                +

                                মজার একটা ব্যাপার হচ্ছে এই ফাংশনটি ওয়েব এ্যাড্রেসও সাপোর্ট করে, অর্থাৎ ওয়েবে থাকা কোন কন্টেন্টও আপনি পড়তে পারবেন এভাবে:

                                +
                                <?php
                                +$content = file_get_contents("http://masnun.com");
                                +var_dump($content);
                                +
                                +

                                ফাইল ডিলিট করা

                                +

                                ফাইল ডিলিট করার জন্য আমরা unlink ফাংশনটি ব্যবহার করি ।

                                +
                                <?php
                                +unlink("./people.txt");
                                +
                                + + +
                                + +
                                +
                                +
                                + +

                                results matching ""

                                +
                                  + +
                                  +
                                  + +

                                  No results matching ""

                                  + +
                                  +
                                  +
                                  + +
                                  +
                                  + +
                                  + + + + + + + + + + + + + + +
                                  + + +
                                  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/functions.html b/_book/functions.html new file mode 100644 index 0000000..c5ff2f3 --- /dev/null +++ b/_book/functions.html @@ -0,0 +1,913 @@ + + + + + + ফাংশনস · HonKit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                  +
                                  + + + + + + + + +
                                  + +
                                  + +
                                  + + + + + + + + +
                                  +
                                  + +
                                  +
                                  + +
                                  + +

                                  ফাংশনস

                                  +

                                  ফাংশন মুলত কিছু স্টেটমেন্টের সমন্বয়ে তৈরি একটি কোড ব্লক যা একটি প্রোগ্রামে বার বার রিইউজ করা সম্ভব। পিএইচপি স্ট্যান্ডার্ড লাইব্রেরীতে অসংখ্যা বিল্টইন ফাংশন রয়েছে যেগুলো আপনি খুব সহজেই ব্যবহার করতে পারেন । এছাড়াও আপনি চাইলে আপনার প্রয়োজনমত ফাংশন লিখে নিতে পারেন

                                  +

                                  বিল্টইন ফাংশন

                                  +

                                  পিএইচপি তে বাই ডিফল্ট যেসব ফাংশন আগেই তৈরি করা থাকে সেগুলোকেই আমরা বিল্ট ইন ফাংশন বলি । এগুলো আমাদের জন্য আগেই তৈরি করা তাকে, আমাদের কাজ শুধু কল করা ।

                                  +
                                  <?php
                                  +var_dump("This is .....");
                                  +?>
                                  +
                                  +

                                  ইউজার ডিফাইনড ফাংশন

                                  +

                                  আমাদের নানা কাজে নানা ধরণের ফাংশন প্রয়োজন হয়, এই সব ক্ষেত্রে আমরা নিজেরাই ফাংশন তৈরি করে নিতে পারি বা অন্যের তৈরি করা ফাংশন ব্যবহার করতে পারি । যে সব ফাংশন ইউজার অর্থাৎ আমাদের (আমার নিজের বা অন্য কোন ডেভেলপারের) তৈরি করা সেগুলোকে ইউজার ডিফাইনড ফাংশন বলা হয় ।

                                  +
                                  <?php
                                  +function sayHello($name)
                                  +{
                                  +    return "Hello {$name}!";
                                  +}
                                  +?>
                                  +
                                  +

                                  এখানে আমরা একটি ইউজার ডিফাইনড ফাংশন দেখছি, এই ফাংশনটি একটি নাম এ্যাক্সেপ্ট করে একটি সুন্দর গ্রিটিং রিটার্ন করে ।

                                  +

                                  ডিফাইনিং ফাংশন

                                  +

                                  যেকোন ইউজার ডিফাইনড ফাংশন লিখতে হলে আপনাকে নিচের সিনট্যাক্স অনুসরণ করতে হবে:

                                  +
                                  <?php
                                  +function functionName($arg1,$arg2)
                                  +{
                                  +    // কোড ব্লক 
                                  +}
                                  +?>
                                  +
                                  +

                                  প্রথমে ফাংশন কিওয়ার্ড, তারপর ফাংশনের নাম, এরপর ব্রাকেটে প্যারামিটার লিস্ট, এরপর ফাংশনের মূল বডি যেটি কিনা একটি কোড ব্লক ।

                                  +

                                  ফাংশনের নাম অবশ্যই ইউনিক হতে হবে, নাম করনের ক্ষেত্রে পিএইচপির সচারচার নিয়মগুলোই অনুসরন করা হয় । ফাংশনের প্যারামিটার ফাকা থাকতে পারে । অধিকাংশ ফাংশনই প্রসেসিং এর পর একটা ভ্যালু রিটার্ন করে, এটাকে রিটার্ন ভ্যালু বলা হয় । তবে কখনো কখনো ফাংশন ভ্যালু নাও রিটার্ন করতে পারে । এই ধরনের ফাংশনকে ভয়েড ফাংশন বলা হয় ।

                                  +

                                  প্যারামিটার ও আর্গুমেন্ট

                                  +

                                  একটি ফাংশন যেসব ইনপুট গ্রহন করে এগুলোই হলো প্যারামিটার । প্যারামিটার গুলো ভ্যারিয়েবল হিসেবে ডিফাইন করা হয় এবং ফাংশন বডির ভিতরে ঐ প্যারামিটারগুলোর ভ্যালু আমরা ঐ ভ্যারিয়েবলগুলো থেকে পাই ।

                                  +

                                  আর ফাংশন কল করার সময় ঐ প্যারামিটারগুলোর জন্য ভ্যালু পাস করার জন্য যে এক্সপ্রেশন ব্যবহার করি সেটাই হলো আর্গুমেন্ট ।

                                  +

                                  সহজ ভাষায়, ফাংশন ডিফাইন করার সময় ব্যবহৃত ভ্যারিয়েবলগুলো প্যারামিটার, কল করার সময় ফাংশন টাকে যেই ভ্যালু পাস করে কল করি তা হলো আর্গুমেন্ট ।

                                  +

                                  উদাহরণ:

                                  +
                                  <?php
                                  +function testFunc($name, $age) 
                                  +{
                                  +
                                  +}
                                  +
                                  +testFunc("masnun", 5*4)
                                  +
                                  +

                                  এখানে $name এবং $age হলো প্যারামিটার, "masnun" এবং 5*4 হলো আর্গুমেন্ট । তবে প্রায়শই আমরা দেখি এই দুটো টার্ম এর একটার জায়গায় আরেকটা টার্ম ব্যবহৃত হতে ।

                                  +

                                  প্যারামিটার ছাড়া ফাংশন

                                  +
                                  <?php
                                  +function functionName()
                                  +{
                                  +   echo "Hi i don't have any argument!";
                                  +}
                                  +?>
                                  +
                                  +

                                  এই ফাংশনটিতে কোন প্যারামিটার নেই। অর্থাৎ একে কল করার সময় কোন আর্গুমেন্ট পাস করাতে হবে না। অনেকটা এই রকম করে functionName(); । প্যারামিটার না নিলে প্যারামিটার লিস্ট এর ব্রাকেট টা আমরা এভাবে ফাকাই রাখবো ।

                                  +

                                  প্যারামিটার সহ ফাংশন

                                  +
                                  <?php
                                  +function functionName($arg1,$arg2)
                                  +{
                                  +   echo $arg1;
                                  +   echo $arg2;
                                  +}
                                  +?>
                                  +
                                  +

                                  প্যারামিটার গুলো ব্রাকেটের মধ্যে কমা দিয়ে আলাদা করা হয় । এই ফাংশনটিতে দুইটি প্যারামিটার আছে $arg1 এবং $arg2 , এই ফাংশনটিকে কল করতে হলে ফাংশনের মধ্যে এই দুইটি প্যারামিটার এর জন্য আর্গুমেন্ট পাস করাতে হবে। অনেকটা এই রকম করে functionName('This is arg 1','This is 2');, যদি ফাংশনটি কল করার সময় আর্গুমেন্টগুলো না থাকে তবে আর্গুমেন্ট মিসিং এরর দেখাবে। তাই এগুলো রিকোয়ারড আর্গুমেন্ট ।

                                  +

                                  পিএইচপি ফাংশনে একটি প্যারামিটারের ডিফল্ট ভ্যালু ডিফাইন করে দেওয়া যায় । যেমন:

                                  +
                                  <?php
                                  +function functionName($arg1="default value")
                                  +{
                                  +   echo $arg1;
                                  +}
                                  +?>
                                  +
                                  +

                                  এই ফাংশনটি কল করার সময় কোন আর্গুমেন্টের ভ্যালু না দিলেও চলবে (functionName();) । সেক্ষেত্রে $arg1 এর ভ্যালু হবে তার ডিফল্ট ভ্যালু । এভাবেই আমরা যে কোন প্যারামিটারের ডিফল্ট ভ্যালু ডিফাইন করে দিয়ে সেই প্যারামিটারটিকে অপশনাল প্যারামিটারে পরিনত করতে পারি ।

                                  +

                                  রিটার্ন ভ্যালু

                                  +

                                  পূর্বে ব্যবহৃত ইউজার ডিফাইনড ফাংশনগুলোতে কোন ভ্যালু রিটার্ন করা হয় নি, সরাসরি আউটপুট দেওয়া হয়েছে। সরাসরি আউটপুট দেখানোর পাশাপাশি ফাংশনগুলো ভ্যালু রিটার্ন করতে পারে যেগুলো আমরা কোন এক্সপ্রেশনে ব্যবহার করতে পারি ।

                                  +

                                  return কিওয়ার্ডটি ব্যবহার করে ভ্যালু রিটার্ন করা হয়।

                                  +
                                  <?php
                                  +function functionName($arg1,$arg2)
                                  +{
                                  +   return $arg1.$arg2;
                                  +}
                                  +?>
                                  +
                                  +

                                  ভ্যারিয়েবল ফাংশন

                                  +

                                  আমরা চাইলে একটি ফাংশনকে ভ্যারিয়েবল ব্যবহার করে কল করতে পারি । এক্ষেত্রে আমরা ফাংশনটির নাম একটি ভ্যারিয়েবল এ এ্যাসাইন করি । এরপর ঐ ভ্যারিয়েবলটির পর () ব্যবহার করে ফাংশনটি কল করি । উদাহরণ দেখি:

                                  +
                                  <?php
                                  +function foo() {
                                  +    echo "In foo()<br />\n";
                                  +}
                                  +
                                  +function bar($arg = '')
                                  +{
                                  +    echo "In bar(); argument was '$arg'.<br />\n";
                                  +}
                                  +
                                  +// This is a wrapper function around echo
                                  +function echoit($string)
                                  +{
                                  +    echo $string;
                                  +}
                                  +
                                  +$func = 'foo';
                                  +$func();        // This calls foo()
                                  +
                                  +$func = 'bar';
                                  +$func('test');  // This calls bar()
                                  +
                                  +$func = 'echoit';
                                  +$func('test');  // This calls echoit()
                                  +?>
                                  +
                                  +

                                  [উদাহরনটি পিএইচপি ম্যানুয়াল থেকে নেওয়া]

                                  +

                                  ফাংশনে ভ্যারিয়েবলের ব্যবহার

                                  +

                                  ইতোমধ্যে আমরা দেখেছি ফাংশনে কিভাবে আর্গুমেন্ট পাস করতে হয়। মুলত এই আর্গুমেন্ট গুলো সংরক্ষণ করা হয় লোকাল ভ্যারিয়েবল এ। এই ভ্যারিয়েবলগুলোকে ফাংশনের বাইরে থেকে এক্সেস করা যায় না। ফাংশনটি যখন কল করা হবে তখন এই ভ্যারিয়েবলগুলো মেমোরিতে সংরক্ষিত হবে। ফাংশন শেষে এই ভ্যারিয়েবলগুলোর আর কোন অস্বিত্ব থাকবে না ।

                                  +

                                  পিএইচপিতে মুলত দুই ধরনের ভ্যারিয়েবল এর ধারণা প্রচলিত, একটি হচ্ছে global ভ্যারিয়েবল আর অন্যটি local ভ্যারিয়েবল। সাধারণত কোড ব্লকের বাইরের পিএইচপিতে ভ্যারিয়েবল গুলো গ্লোবাল হয়, এসব ক্ষেত্রে আপনার প্রোগ্রামে একই নামে দুটি ভ্যারিয়েবল লিখলে ২য় টির দ্বারা প্রথমটির ভ্যালু প্রতিস্থাপিত হবে। অন্যদিকে ফাংশন / মেথডে ব্যবহারিত ভ্যারিয়েবলগুলো সাধারনত লোকাল ভ্যারিয়েবল হয়। ঐ ভ্যারিয়েবলগুলোকে শুধুমাত্র ওই মেথড / ফাংশনের মধ্যে ব্যবহার করা যাবে।

                                  +
                                  <?php
                                  +$myvar = 100; // $myvar একটি গ্লোবাল ভ্যারিয়েবল
                                  +
                                  +function myFunc()
                                  +{
                                  +    $myvar = 50; // $myvar একটি লোকাল ভ্যারিয়েবল
                                  +}
                                  +?>
                                  +
                                  +

                                  চাইলে গ্লোবাল ভ্যারিয়েবলগুলোকে সরাসির ফাংশন / মেথডের ভেতরে ব্যবহার করা যায়। এর জন্য global স্টেটমেন্ট ব্যবহার করতে হবে। নিচের উদাহরনটি দেখুনঃ

                                  +
                                  <?php
                                  +$myvar = 100; // $myvar একটি গ্লোবাল ভ্যারিয়েবল
                                  +
                                  +function myFunc()
                                  +{
                                  +    global $myvar;
                                  +    echo $myvar // $myvar একটি গ্লোবাল ভ্যারিয়েবল
                                  +}
                                  +?>
                                  +
                                  +

                                  এখানে আমরা ফাংশনের ভিতর থেকেও গ্লোবাল $myvar ভ্যারিয়েবলটি এ্যাক্সেস করেছি ।

                                  +

                                  পিএইচপিতে যখন কোন ফাংশনে / মেথডে কোন লোকাল ভ্যারিয়েবল ব্যবহার করা হয় তখন ফাংশনটি কল হওয়ার সময় ভ্যারিয়েবলটি তৈরি হয় এবং কল শেষ হলে ধ্বংস হয়ে যায়। অনেক সময় আমাদের ওই ফাংশনটি পরবর্তীতে কল করা হলে ভ্যারিয়েবলটির আগের মান জানার দরকার হতে পারে। static স্টেটমেন্ট ব্যবহার করে ওই ভ্যারিয়েবলটির ভ্যালু পরবর্তী কলের জন্য সংরক্ষন করা সম্ভব । নিচে একটি উদাহরন দেওয়া হল ।

                                  +

                                  মনে করা যাক আমাদের একটি ফাংশন আছে যার নাম query() এখন আমাদের পুরো প্রোগ্রামে সকল ডাটাবেস কুয়েরির জন্য আমরা এই ফাংশনটি ব্যবহার করব। এই কারনে আমারা ফাংশনের মধ্যে একটি static ভ্যারিয়েবল ব্যবহার করব। যা কতবার এই ফাংশনটিকে কল করা হয়ে তার হিসাব রাখবে।

                                  +
                                  <?php
                                  +function query()
                                  +{
                                  +    static $count;
                                  +    $count += 1;
                                  +    $queryResult = "This is Query Result";
                                  +    return array('query' => $queryResult, 'count' => $count);
                                  +}
                                  +// চারবার কল করা হয়েছে।
                                  +var_dump(query());
                                  +var_dump(query());
                                  +var_dump(query());
                                  +var_dump(query());
                                  +?>
                                  +
                                  +

                                  আউটপুটঃ

                                  +
                                  array (size=2)
                                  +  'query' => string 'This is Query Result' (length=20)
                                  +  'count' => int 1
                                  +array (size=2)
                                  +  'query' => string 'This is Query Result' (length=20)
                                  +  'count' => int 2
                                  +array (size=2)
                                  +  'query' => string 'This is Query Result' (length=20)
                                  +  'count' => int 3
                                  +array (size=2)
                                  +  'query' => string 'This is Query Result' (length=20)
                                  +  'count' => int 4
                                  +
                                  +

                                  এনোনিমাস ফাংশন

                                  +

                                  এই জাতীয় ফাংশনগুলোর কোন স্পেসিফিক নাম থাকে না। উদাহরন হিসাবে নিচের কোডটি দেখুন।

                                  +
                                  <?php
                                  +$data = function (){
                                  +    $val = array();
                                  +    for($i=0;$i<10;$i++)
                                  +    {
                                  +        $val[] = $i;
                                  +    }
                                  +    return $val;
                                  +};
                                  +
                                  +var_dump($data());
                                  +?>
                                  +
                                  +

                                  এখানে আমরা ফাংশনটির কোন নাম দেইনি কিন্তু বাকি অংশগুলো ঠিক রেখেছি । এই ফাংশনটির কোন নাম না থাকলেও আমরা $data ভ্যারিয়েবলটি ব্যবহার করে ফাংশনটি কল করতে পারি ।

                                  +

                                  এনোনিমাস ফাংশনে স্বাভাবিক ফাংশনের মত করেই আর্গুমেন্ট ব্যবহার করা যায়, নিচের কোড দেখুনঃ

                                  +
                                  <?php
                                  +$data = function ($limit){
                                  +    $val = array();
                                  +    for($i=0;$i<$limit;$i++)
                                  +    {
                                  +        $val[] = $i;
                                  +    }
                                  +    return $val;
                                  +};
                                  +
                                  +var_dump($data(20));
                                  +?>
                                  +
                                  +

                                  রিকার্সিভ ফাংশন

                                  +

                                  কোন ফাংশন যখন নিজে নিজেকে কল করে তখন তাকে রিকার্সিভ ফাংশন বলা হয়ে থাকে। নিচে ফ্যাক্টোরিয়াল এর উদাহরন দেওয়া হলো । এখানে $n এর ভ্যালু কমিয়ে কমিয়ে ফাংশনটি রিকার্সিভলি কল করা হয় । যখন $n এর ভ্যালু শূন্য হয় তখনই সে থেমে যায় । যে শর্তের উপর নির্ভর করে ফাংশনটি নিজেকে আবার কল করে বা থেমে যায় এটাকে বেইজ কন্ডিশন বা বেইজ কেইস বলা হয় । রিকার্সিভ ফাংশনে বেইজ কেইস সেট করে দেওয়া জরুরী নাহলে এই রিকার্শন থিওরেটিক্যালি থামবে না । প্র্যাক্টিকালি পিএইচপি একটি নির্দিষ্ট লেভেল এর রিকার্শন এর পর ইরর থ্রো করবে ।

                                  +

                                  যদি রিকার্সিভ ফাংশন থেকে ডাটা রিটার্ন করতে হয় তবে মূল ফাংশনের ভেতরে নিজেকে আবার কল করার সময় ফাংশনের সামনে return লাগিয়ে কল করতে হবে।

                                  +
                                  <?php
                                  +function fact($n) {
                                  +  if ($n === 0) { // our base case
                                  +     return 1;
                                  +  }
                                  +  else {
                                  +     return $n * fact($n-1); // <--calling itself.
                                  +  }
                                  +}
                                  +
                                  +var_dump(fact(10));
                                  +?>
                                  +
                                  +

                                  এখানে ফাংশনটি নিজেকে কল করে অপেক্ষা করতে থাকে সেটির রিটার্ন ভ্যালুর জন্য । সেই ফাংশনটি আবার নিজেকে কল করে অপেক্ষা করতে তাকে । এভাবে একটা নেস্টেড অবস্থা তৈরি হয় । এবং সাধারনত সব শেষে কল করা ফাংশন (যেটি বেইজ কেইস ম্যাচ করে) সেটি আগে ভ্যালু রিটার্ন করে এবং কন্ট্রোল তার আগের কলারকে ফিরিয়ে দেয় । এভাবেই রিকার্শন কাজ করে ।

                                  +

                                  সাধারণত ফাংশন নেস্টিং ৯৯ বার পর্যন্ত লিমিট করা থাকে। তাই Fibonacci জাতীয় প্রোগ্রাম for / while / if দিয়ে করা উচিত।

                                  + + +
                                  + +
                                  +
                                  +
                                  + +

                                  results matching ""

                                  +
                                    + +
                                    +
                                    + +

                                    No results matching ""

                                    + +
                                    +
                                    +
                                    + +
                                    +
                                    + +
                                    + + + + + + + + + + + + + + +
                                    + + +
                                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/_book/gitbook/@honkit/honkit-plugin-fontsettings/fontsettings.js b/_book/gitbook/@honkit/honkit-plugin-fontsettings/fontsettings.js new file mode 100644 index 0000000..b5c86eb --- /dev/null +++ b/_book/gitbook/@honkit/honkit-plugin-fontsettings/fontsettings.js @@ -0,0 +1,238 @@ +require(["gitbook", "jquery"], (gitbook, $) => { + // Configuration + const MAX_SIZE = 4; + const MIN_SIZE = 0; + let BUTTON_ID; + + // Current fontsettings state + let fontState; + + // Default themes + let THEMES = [ + { + config: "white", + text: "White", + id: 0 + }, + { + config: "sepia", + text: "Sepia", + id: 1 + }, + { + config: "night", + text: "Night", + id: 2 + } + ]; + + // Default font families + let FAMILIES = [ + { + config: "serif", + text: "Serif", + id: 0 + }, + { + config: "sans", + text: "Sans", + id: 1 + } + ]; + + // Return configured themes + function getThemes() { + return THEMES; + } + + // Modify configured themes + function setThemes(themes) { + THEMES = themes; + updateButtons(); + } + + // Return configured font families + function getFamilies() { + return FAMILIES; + } + + // Modify configured font families + function setFamilies(families) { + FAMILIES = families; + updateButtons(); + } + + // Save current font settings + function saveFontSettings() { + gitbook.storage.set("fontState", fontState); + update(); + } + + // Increase font size + function enlargeFontSize(e) { + e.preventDefault(); + if (fontState.size >= MAX_SIZE) return; + + fontState.size++; + saveFontSettings(); + } + + // Decrease font size + function reduceFontSize(e) { + e.preventDefault(); + if (fontState.size <= MIN_SIZE) return; + + fontState.size--; + saveFontSettings(); + } + + // Change font family + function changeFontFamily(configName, e) { + if (e && e instanceof Event) { + e.preventDefault(); + } + + const familyId = getFontFamilyId(configName); + fontState.family = familyId; + saveFontSettings(); + } + + // Change type of color theme + function changeColorTheme(configName, e) { + if (e && e instanceof Event) { + e.preventDefault(); + } + + const $book = gitbook.state.$book; + + // Remove currently applied color theme + if (fontState.theme !== 0) $book.removeClass(`color-theme-${fontState.theme}`); + + // Set new color theme + const themeId = getThemeId(configName); + fontState.theme = themeId; + if (fontState.theme !== 0) $book.addClass(`color-theme-${fontState.theme}`); + + saveFontSettings(); + } + + // Return the correct id for a font-family config key + // Default to first font-family + function getFontFamilyId(configName) { + // Search for plugin configured font family + const configFamily = $.grep(FAMILIES, (family) => { + return family.config == configName; + })[0]; + + // Fallback to default font family + return (configFamily && configFamily.id) || 0; + } + + // Return the correct id for a theme config key + // Default to first theme + function getThemeId(configName) { + // Search for plugin configured theme + const configTheme = $.grep(THEMES, (theme) => { + return theme.config == configName; + })[0]; + + // Fallback to default theme + return (configTheme && configTheme.id) || 0; + } + + function update() { + const $book = gitbook.state.$book; + + $(".font-settings .font-family-list li").removeClass("active"); + $(`.font-settings .font-family-list li:nth-child(${fontState.family + 1})`).addClass("active"); + + $book[0].className = $book[0].className.replace(/\bfont-\S+/g, ""); + $book.addClass(`font-size-${fontState.size}`); + $book.addClass(`font-family-${fontState.family}`); + + if (fontState.theme !== 0) { + $book[0].className = $book[0].className.replace(/\bcolor-theme-\S+/g, ""); + $book.addClass(`color-theme-${fontState.theme}`); + } + } + + function init(config) { + // Search for plugin configured font family + const configFamily = getFontFamilyId(config.family); + const configTheme = getThemeId(config.theme); + + // Instantiate font state object + fontState = gitbook.storage.get("fontState", { + size: config.size || 2, + family: configFamily, + theme: configTheme + }); + + update(); + } + + function updateButtons() { + // Remove existing fontsettings buttons + if (BUTTON_ID) { + gitbook.toolbar.removeButton(BUTTON_ID); + } + + // Create buttons in toolbar + BUTTON_ID = gitbook.toolbar.createButton({ + icon: "fa fa-font", + label: "Font Settings", + className: "font-settings", + dropdown: [ + [ + { + text: "A", + className: "font-reduce", + onClick: reduceFontSize + }, + { + text: "A", + className: "font-enlarge", + onClick: enlargeFontSize + } + ], + $.map(FAMILIES, (family) => { + family.onClick = function (e) { + return changeFontFamily(family.config, e); + }; + + return family; + }), + $.map(THEMES, (theme) => { + theme.onClick = function (e) { + return changeColorTheme(theme.config, e); + }; + + return theme; + }) + ] + }); + } + + // Init configuration at start + gitbook.events.bind("start", (e, config) => { + const opts = config.fontsettings; + + // Generate buttons at start + updateButtons(); + + // Init current settings + init(opts); + }); + + // Expose API + gitbook.fontsettings = { + enlargeFontSize: enlargeFontSize, + reduceFontSize: reduceFontSize, + setTheme: changeColorTheme, + setFamily: changeFontFamily, + getThemes: getThemes, + setThemes: setThemes, + getFamilies: getFamilies, + setFamilies: setFamilies + }; +}); diff --git a/_book/gitbook/@honkit/honkit-plugin-fontsettings/website.css b/_book/gitbook/@honkit/honkit-plugin-fontsettings/website.css new file mode 100644 index 0000000..6871a3b --- /dev/null +++ b/_book/gitbook/@honkit/honkit-plugin-fontsettings/website.css @@ -0,0 +1,309 @@ +/* + * Theme 1 + */ +.color-theme-1 .dropdown-menu { + background-color: #111; + border-color: hsl(194, 5%, 52%); +} +.color-theme-1 .dropdown-menu .dropdown-caret .caret-inner { + border-bottom: 9px solid #111; +} +.color-theme-1 .dropdown-menu .buttons { + border-color: hsl(194, 5%, 52%); +} +.color-theme-1 .dropdown-menu .button { + color: #AFA790; +} +.color-theme-1 .dropdown-menu .button:hover { + color: #73553C; +} +/* + * Theme 2 + */ +.color-theme-2 .dropdown-menu { + background-color: hsl(229, 20%, 22%); + border-color: hsl(230, 19%, 19%); +} +.color-theme-2 .dropdown-menu .dropdown-caret .caret-inner { + border-bottom: 9px solid hsl(229, 20%, 22%); +} +.color-theme-2 .dropdown-menu .buttons { + border-color: hsl(230, 19%, 19%); +} +.color-theme-2 .dropdown-menu .button { + color: hsl(228, 13%, 44%); +} +.color-theme-2 .dropdown-menu .button:hover { + color: hsl(240, 5%, 96%); +} +.book .book-header .font-settings .font-enlarge { + line-height: 30px; + font-size: 1.4em; +} +.book .book-header .font-settings .font-reduce { + line-height: 30px; + font-size: 1em; +} +.book.color-theme-1 .book-body { + color: #704214; + background: #F3EACB; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section { + background: #F3EACB; +} +.book.color-theme-1 #book-search-input { + background: transparent; +} +.book.color-theme-1 #book-search-results .search-results .has-results .search-results-item { + color: #b16820; +} +.book.color-theme-2 .book-body { + color: hsl(214, 29%, 80%); + background: hsl(228, 21%, 14%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section { + background: hsl(228, 21%, 14%); +} +.book.color-theme-2 #book-search-input { + background: transparent; +} +.book.color-theme-2 #book-search-results .search-results .has-results .search-results-item { + color: hsl(214, 29%, 65%); +} +.book.font-size-0 .book-body .page-inner section { + font-size: 1.2rem; +} +.book.font-size-1 .book-body .page-inner section { + font-size: 1.4rem; +} +.book.font-size-2 .book-body .page-inner section { + font-size: 1.6rem; +} +.book.font-size-3 .book-body .page-inner section { + font-size: 2.2rem; +} +.book.font-size-4 .book-body .page-inner section { + font-size: 4rem; +} +.book.font-family-0 { + font-family: Georgia, serif; +} +.book.font-family-1 { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal { + color: #704214; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal a { + color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h3, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h4, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h5, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { + color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h1, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h2 { + border-color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal h6 { + color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal hr { + background-color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal blockquote { + border-color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { + background: #fdf6e3; + color: #657b83; + border-color: #f8df9c; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal .highlight { + background-color: inherit; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table th, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table td { + border-color: #f5d06c; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr { + color: inherit; + background-color: #fdf6e3; + border-color: #444; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { + background-color: #fbeecb; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal { + color: hsl(214, 29%, 80%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal a { + color: hsl(193, 61%, 53%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h3, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h4, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h5, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { + color: hsl(60, 100%, 99%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h1, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h2 { + border-color: hsl(230, 17%, 26%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal h6 { + color: hsl(230, 17%, 26%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal hr { + background-color: hsl(230, 17%, 26%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal blockquote { + border-color: hsl(230, 17%, 26%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { + color: hsl(206, 43%, 73%); + background: hsl(229, 20%, 22%); + border-color: hsl(229, 20%, 22%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal .highlight { + background-color: hsl(233, 18%, 19%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table th, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table td { + border-color: hsl(230, 17%, 28%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr { + color: hsl(216, 24%, 77%); + background-color: hsl(229, 19%, 22%); + border-color: hsl(230, 17%, 28%); +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal table tr:nth-child(2n) { + background-color: hsl(229, 17%, 25%); +} +.book.color-theme-1 .book-header { + color: #AFA790; + background: transparent; +} +.book.color-theme-1 .book-header .btn { + color: #AFA790; +} +.book.color-theme-1 .book-header .btn:hover { + color: #73553C; + background: none; +} +.book.color-theme-1 .book-header h1 { + color: #704214; +} +.book.color-theme-2 .book-header { + color: #7e888b; + background: transparent; +} +.book.color-theme-2 .book-header .btn { + color: hsl(230, 17%, 28%); +} +.book.color-theme-2 .book-header .btn:hover { + color: hsl(60, 100%, 98%); + background: none; +} +.book.color-theme-2 .book-header h1 { + color: hsl(214, 29%, 80%); +} +.book.color-theme-1 .book-body .navigation { + color: #AFA790; +} +.book.color-theme-1 .book-body .navigation:hover { + color: #73553C; +} +.book.color-theme-2 .book-body .navigation { + color: hsl(224, 19%, 27%); +} +.book.color-theme-2 .book-body .navigation:hover { + color: hsl(60, 100%, 98%); +} +/* + * Theme 1 + */ +.book.color-theme-1 .book-summary { + color: #AFA790; + background: #111; + border-right: 1px solid rgba(0, 0, 0, 0.07); +} +.book.color-theme-1 .book-summary .book-search, +.book.color-theme-1 .book-summary #book-search-input { + background: transparent; +} +.book.color-theme-1 .book-summary .book-search input, +.book.color-theme-1 .book-summary #book-search-input input, +.book.color-theme-1 .book-summary .book-search input:focus, +.book.color-theme-1 .book-summary #book-search-input input:focus { + border: 1px solid transparent; +} +.book.color-theme-1 .book-summary ul.summary li.divider { + background: hsl(194, 5%, 52%); + box-shadow: none; +} +.book.color-theme-1 .book-summary ul.summary li i.fa-check { + color: hsl(120, 60%, 50%); +} +.book.color-theme-1 .book-summary ul.summary li.done > a { + color: #877F6A; +} +.book.color-theme-1 .book-summary ul.summary li a, +.book.color-theme-1 .book-summary ul.summary li span { + color: #877F6A; + background: transparent; + font-weight: normal; +} +.book.color-theme-1 .book-summary ul.summary li.active > a, +.book.color-theme-1 .book-summary ul.summary li a:hover { + color: #704214; + background: transparent; + font-weight: normal; +} +/* + * Theme 2 + */ +.book.color-theme-2 .book-summary { + color: hsl(226, 20%, 78%); + background: hsl(229, 20%, 22%); + border-right: none; +} +.book.color-theme-2 .book-summary .book-search, +.book.color-theme-2 .book-summary #book-search-input { + background: transparent; +} +.book.color-theme-2 .book-summary .book-search input, +.book.color-theme-2 .book-summary #book-search-input input, +.book.color-theme-2 .book-summary .book-search input:focus, +.book.color-theme-2 .book-summary #book-search-input input:focus { + border: 1px solid transparent; +} +.book.color-theme-2 .book-summary ul.summary li.divider { + background: hsl(230, 19%, 19%); + box-shadow: none; +} +.book.color-theme-2 .book-summary ul.summary li i.fa-check { + color: hsl(120, 60%, 50%); +} +.book.color-theme-2 .book-summary ul.summary li.done > a { + color: hsl(227, 13%, 44%); +} +.book.color-theme-2 .book-summary ul.summary li a, +.book.color-theme-2 .book-summary ul.summary li span { + color: hsl(226, 22%, 80%); + background: transparent; + font-weight: 600; +} +.book.color-theme-2 .book-summary ul.summary li.active > a, +.book.color-theme-2 .book-summary ul.summary li a:hover { + color: hsl(240, 5%, 96%); + background: hsl(233, 19%, 18%); + font-weight: 600; +} diff --git a/_book/gitbook/@honkit/honkit-plugin-highlight/ebook.css b/_book/gitbook/@honkit/honkit-plugin-highlight/ebook.css new file mode 100644 index 0000000..9fcf623 --- /dev/null +++ b/_book/gitbook/@honkit/honkit-plugin-highlight/ebook.css @@ -0,0 +1,215 @@ +pre, +code { + /* From highlight.js@11.10.0/styles/tomorrow.css */ + /*! + Theme: Tomorrow + Author: Chris Kempson (http://chriskempson.com) + License: ~ MIT (or more permissive) [via base16-schemes-source] + Maintainer: @highlightjs/core-team + Version: 2021.09.0 +*/ + /* + WARNING: DO NOT EDIT THIS FILE DIRECTLY. + + This theme file was auto-generated from the Base16 scheme tomorrow + by the Highlight.js Base16 template builder. + + - https://github.com/highlightjs/base16-highlightjs +*/ + /* +base00 #ffffff Default Background +base01 #e0e0e0 Lighter Background (Used for status bars, line number and folding marks) +base02 #d6d6d6 Selection Background +base03 #8e908c Comments, Invisibles, Line Highlighting +base04 #969896 Dark Foreground (Used for status bars) +base05 #4d4d4c Default Foreground, Caret, Delimiters, Operators +base06 #282a2e Light Foreground (Not often used) +base07 #1d1f21 Light Background (Not often used) +base08 #c82829 Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted +base09 #f5871f Integers, Boolean, Constants, XML Attributes, Markup Link Url +base0A #eab700 Classes, Markup Bold, Search Text Background +base0B #718c00 Strings, Inherited Class, Markup Code, Diff Inserted +base0C #3e999f Support, Regular Expressions, Escape Characters, Markup Quotes +base0D #4271ae Functions, Methods, Attribute IDs, Headings +base0E #8959a8 Keywords, Storage, Selector, Markup Italic, Diff Changed +base0F #a3685a Deprecated, Opening/Closing Embedded Language Tags, e.g. +*/ + /* purposely do not highlight these things */ + /* base03 - #8e908c - Comments, Invisibles, Line Highlighting */ + /* base04 - #969896 - Dark Foreground (Used for status bars) */ + /* base05 - #4d4d4c - Default Foreground, Caret, Delimiters, Operators */ + /* base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted */ + /* base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url */ + /* base0A - Classes, Markup Bold, Search Text Background */ + /* base0B - Strings, Inherited Class, Markup Code, Diff Inserted */ + /* base0C - Support, Regular Expressions, Escape Characters, Markup Quotes */ + /* guessing */ + /* base0D - Functions, Methods, Attribute IDs, Headings */ + /* base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed */ + /* .hljs-selector-id, */ + /* .hljs-selector-class, */ + /* .hljs-selector-attr, */ + /* .hljs-selector-pseudo, */ + /* base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. */ + /* + prevent top level .keyword and .string scopes + from leaking into meta by accident +*/ + /* for v10 compatible themes */ +} +pre pre code.hljs, +code pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em; +} +pre code.hljs, +code code.hljs { + padding: 3px 5px; +} +pre pre code.hljs, +code pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em; +} +pre code.hljs, +code code.hljs { + padding: 3px 5px; +} +pre .hljs, +code .hljs { + color: #4d4d4c; + background: #ffffff; +} +pre .hljs::selection, +code .hljs::selection, +pre .hljs ::selection, +code .hljs ::selection { + background-color: #d6d6d6; + color: #4d4d4c; +} +pre .hljs-comment, +code .hljs-comment { + color: #8e908c; +} +pre .hljs-tag, +code .hljs-tag { + color: #969896; +} +pre .hljs-subst, +code .hljs-subst, +pre .hljs-punctuation, +code .hljs-punctuation, +pre .hljs-operator, +code .hljs-operator { + color: #4d4d4c; +} +pre .hljs-operator, +code .hljs-operator { + opacity: 0.7; +} +pre .hljs-bullet, +code .hljs-bullet, +pre .hljs-variable, +code .hljs-variable, +pre .hljs-template-variable, +code .hljs-template-variable, +pre .hljs-selector-tag, +code .hljs-selector-tag, +pre .hljs-name, +code .hljs-name, +pre .hljs-deletion, +code .hljs-deletion { + color: #c82829; +} +pre .hljs-symbol, +code .hljs-symbol, +pre .hljs-number, +code .hljs-number, +pre .hljs-link, +code .hljs-link, +pre .hljs-attr, +code .hljs-attr, +pre .hljs-variable.constant_, +code .hljs-variable.constant_, +pre .hljs-literal, +code .hljs-literal { + color: #f5871f; +} +pre .hljs-title, +code .hljs-title, +pre .hljs-class .hljs-title, +code .hljs-class .hljs-title, +pre .hljs-title.class_, +code .hljs-title.class_ { + color: #eab700; +} +pre .hljs-strong, +code .hljs-strong { + font-weight: bold; + color: #eab700; +} +pre .hljs-code, +code .hljs-code, +pre .hljs-addition, +code .hljs-addition, +pre .hljs-title.class_.inherited__, +code .hljs-title.class_.inherited__, +pre .hljs-string, +code .hljs-string { + color: #718c00; +} +pre .hljs-built_in, +code .hljs-built_in, +pre .hljs-doctag, +code .hljs-doctag, +pre .hljs-quote, +code .hljs-quote, +pre .hljs-keyword.hljs-atrule, +code .hljs-keyword.hljs-atrule, +pre .hljs-regexp, +code .hljs-regexp { + color: #3e999f; +} +pre .hljs-function .hljs-title, +code .hljs-function .hljs-title, +pre .hljs-attribute, +code .hljs-attribute, +pre .ruby .hljs-property, +code .ruby .hljs-property, +pre .hljs-title.function_, +code .hljs-title.function_, +pre .hljs-section, +code .hljs-section { + color: #4271ae; +} +pre .hljs-type, +code .hljs-type, +pre .hljs-template-tag, +code .hljs-template-tag, +pre .diff .hljs-meta, +code .diff .hljs-meta, +pre .hljs-keyword, +code .hljs-keyword { + color: #8959a8; +} +pre .hljs-emphasis, +code .hljs-emphasis { + color: #8959a8; + font-style: italic; +} +pre .hljs-meta, +code .hljs-meta, +pre .hljs-meta .hljs-keyword, +code .hljs-meta .hljs-keyword, +pre .hljs-meta .hljs-string, +code .hljs-meta .hljs-string { + color: #a3685a; +} +pre .hljs-meta .hljs-keyword, +code .hljs-meta .hljs-keyword, +pre .hljs-meta-keyword, +code .hljs-meta-keyword { + font-weight: bold; +} diff --git a/_book/gitbook/@honkit/honkit-plugin-highlight/website.css b/_book/gitbook/@honkit/honkit-plugin-highlight/website.css new file mode 100644 index 0000000..48c8529 --- /dev/null +++ b/_book/gitbook/@honkit/honkit-plugin-highlight/website.css @@ -0,0 +1,533 @@ +.book .book-body .page-wrapper .page-inner section.normal pre, +.book .book-body .page-wrapper .page-inner section.normal code { + /* From highlight.js@11.10.0/styles/tomorrow.css */ + /*! + Theme: Tomorrow + Author: Chris Kempson (http://chriskempson.com) + License: ~ MIT (or more permissive) [via base16-schemes-source] + Maintainer: @highlightjs/core-team + Version: 2021.09.0 +*/ + /* + WARNING: DO NOT EDIT THIS FILE DIRECTLY. + + This theme file was auto-generated from the Base16 scheme tomorrow + by the Highlight.js Base16 template builder. + + - https://github.com/highlightjs/base16-highlightjs +*/ + /* +base00 #ffffff Default Background +base01 #e0e0e0 Lighter Background (Used for status bars, line number and folding marks) +base02 #d6d6d6 Selection Background +base03 #8e908c Comments, Invisibles, Line Highlighting +base04 #969896 Dark Foreground (Used for status bars) +base05 #4d4d4c Default Foreground, Caret, Delimiters, Operators +base06 #282a2e Light Foreground (Not often used) +base07 #1d1f21 Light Background (Not often used) +base08 #c82829 Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted +base09 #f5871f Integers, Boolean, Constants, XML Attributes, Markup Link Url +base0A #eab700 Classes, Markup Bold, Search Text Background +base0B #718c00 Strings, Inherited Class, Markup Code, Diff Inserted +base0C #3e999f Support, Regular Expressions, Escape Characters, Markup Quotes +base0D #4271ae Functions, Methods, Attribute IDs, Headings +base0E #8959a8 Keywords, Storage, Selector, Markup Italic, Diff Changed +base0F #a3685a Deprecated, Opening/Closing Embedded Language Tags, e.g. +*/ + /* purposely do not highlight these things */ + /* base03 - #8e908c - Comments, Invisibles, Line Highlighting */ + /* base04 - #969896 - Dark Foreground (Used for status bars) */ + /* base05 - #4d4d4c - Default Foreground, Caret, Delimiters, Operators */ + /* base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted */ + /* base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url */ + /* base0A - Classes, Markup Bold, Search Text Background */ + /* base0B - Strings, Inherited Class, Markup Code, Diff Inserted */ + /* base0C - Support, Regular Expressions, Escape Characters, Markup Quotes */ + /* guessing */ + /* base0D - Functions, Methods, Attribute IDs, Headings */ + /* base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed */ + /* .hljs-selector-id, */ + /* .hljs-selector-class, */ + /* .hljs-selector-attr, */ + /* .hljs-selector-pseudo, */ + /* base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. */ + /* + prevent top level .keyword and .string scopes + from leaking into meta by accident +*/ + /* for v10 compatible themes */ +} +.book .book-body .page-wrapper .page-inner section.normal pre pre code.hljs, +.book .book-body .page-wrapper .page-inner section.normal code pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em; +} +.book .book-body .page-wrapper .page-inner section.normal pre code.hljs, +.book .book-body .page-wrapper .page-inner section.normal code code.hljs { + padding: 3px 5px; +} +.book .book-body .page-wrapper .page-inner section.normal pre pre code.hljs, +.book .book-body .page-wrapper .page-inner section.normal code pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em; +} +.book .book-body .page-wrapper .page-inner section.normal pre code.hljs, +.book .book-body .page-wrapper .page-inner section.normal code code.hljs { + padding: 3px 5px; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs, +.book .book-body .page-wrapper .page-inner section.normal code .hljs { + color: #4d4d4c; + background: #ffffff; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs::selection, +.book .book-body .page-wrapper .page-inner section.normal code .hljs::selection, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs ::selection, +.book .book-body .page-wrapper .page-inner section.normal code .hljs ::selection { + background-color: #d6d6d6; + color: #4d4d4c; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-comment { + color: #8e908c; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-tag { + color: #969896; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-subst, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-subst, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-punctuation, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-punctuation, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-operator, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-operator { + color: #4d4d4c; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-operator, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-operator { + opacity: 0.7; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-bullet, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-bullet, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-variable, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-template-variable, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-template-variable, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-selector-tag, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-selector-tag, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-name, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-name, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-deletion { + color: #c82829; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-symbol, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-number, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-number, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-link, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-link, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-attr, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-attr, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-variable.constant_, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-variable.constant_, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-literal { + color: #f5871f; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-class .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-class .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-title.class_, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-title.class_ { + color: #eab700; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-strong, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-strong { + font-weight: bold; + color: #eab700; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-code, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-code, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-addition, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-title.class_.inherited__, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-title.class_.inherited__, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-string, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-string { + color: #718c00; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-doctag, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-doctag, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-quote, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-quote, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword.hljs-atrule, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-keyword.hljs-atrule, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-regexp { + color: #3e999f; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-function .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-function .hljs-title, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, +.book .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-property, +.book .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-property, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-title.function_, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-title.function_, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-section, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-section { + color: #4271ae; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-type, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-type, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-template-tag, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-template-tag, +.book .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-meta, +.book .book-body .page-wrapper .page-inner section.normal code .diff .hljs-meta, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-keyword { + color: #8959a8; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-emphasis, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-emphasis { + color: #8959a8; + font-style: italic; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-meta, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-meta, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-meta .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-meta .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-meta .hljs-string, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-meta .hljs-string { + color: #a3685a; +} +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-meta .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-meta .hljs-keyword, +.book .book-body .page-wrapper .page-inner section.normal pre .hljs-meta-keyword, +.book .book-body .page-wrapper .page-inner section.normal code .hljs-meta-keyword { + font-weight: bold; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code { + /* From highlight.js@11.10.0/styles/solarized-light.css */ + /*! + Theme: Solarized Light + Author: Ethan Schoonover (modified by aramisgithub) + License: ~ MIT (or more permissive) [via base16-schemes-source] + Maintainer: @highlightjs/core-team + Version: 2021.09.0 +*/ + /* + WARNING: DO NOT EDIT THIS FILE DIRECTLY. + + This theme file was auto-generated from the Base16 scheme solarized-light + by the Highlight.js Base16 template builder. + + - https://github.com/highlightjs/base16-highlightjs +*/ + /* +base00 #fdf6e3 Default Background +base01 #eee8d5 Lighter Background (Used for status bars, line number and folding marks) +base02 #93a1a1 Selection Background +base03 #839496 Comments, Invisibles, Line Highlighting +base04 #657b83 Dark Foreground (Used for status bars) +base05 #586e75 Default Foreground, Caret, Delimiters, Operators +base06 #073642 Light Foreground (Not often used) +base07 #002b36 Light Background (Not often used) +base08 #dc322f Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted +base09 #cb4b16 Integers, Boolean, Constants, XML Attributes, Markup Link Url +base0A #b58900 Classes, Markup Bold, Search Text Background +base0B #859900 Strings, Inherited Class, Markup Code, Diff Inserted +base0C #2aa198 Support, Regular Expressions, Escape Characters, Markup Quotes +base0D #268bd2 Functions, Methods, Attribute IDs, Headings +base0E #6c71c4 Keywords, Storage, Selector, Markup Italic, Diff Changed +base0F #d33682 Deprecated, Opening/Closing Embedded Language Tags, e.g. +*/ + /* purposely do not highlight these things */ + /* base03 - #839496 - Comments, Invisibles, Line Highlighting */ + /* base04 - #657b83 - Dark Foreground (Used for status bars) */ + /* base05 - #586e75 - Default Foreground, Caret, Delimiters, Operators */ + /* base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted */ + /* base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url */ + /* base0A - Classes, Markup Bold, Search Text Background */ + /* base0B - Strings, Inherited Class, Markup Code, Diff Inserted */ + /* base0C - Support, Regular Expressions, Escape Characters, Markup Quotes */ + /* guessing */ + /* base0D - Functions, Methods, Attribute IDs, Headings */ + /* base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed */ + /* .hljs-selector-id, */ + /* .hljs-selector-class, */ + /* .hljs-selector-attr, */ + /* .hljs-selector-pseudo, */ + /* base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. */ + /* + prevent top level .keyword and .string scopes + from leaking into meta by accident +*/ + /* for v10 compatible themes */ +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre pre code.hljs, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre code.hljs, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code code.hljs { + padding: 3px 5px; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre pre code.hljs, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre code.hljs, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code code.hljs { + padding: 3px 5px; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs { + color: #586e75; + background: #fdf6e3; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs::selection, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs::selection, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs ::selection, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs ::selection { + background-color: #93a1a1; + color: #586e75; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-comment { + color: #839496; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-tag { + color: #657b83; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-subst, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-subst, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-punctuation, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-punctuation, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-operator, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-operator { + color: #586e75; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-operator, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-operator { + opacity: 0.7; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-bullet, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-bullet, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-template-variable, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-template-variable, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-selector-tag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-selector-tag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-name, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-name, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion { + color: #dc322f; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-number, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-link, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-link, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attr, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attr, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable.constant_, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-variable.constant_, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-literal { + color: #cb4b16; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-class .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-class .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title.class_, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title.class_ { + color: #b58900; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-strong, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-strong { + font-weight: bold; + color: #b58900; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-code, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-code, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-addition, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title.class_.inherited__, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title.class_.inherited__, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-string { + color: #859900; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-doctag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-doctag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-quote, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-quote, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword.hljs-atrule, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword.hljs-atrule, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp { + color: #2aa198; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-function .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-function .hljs-title, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .ruby .hljs-property, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .ruby .hljs-property, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-title.function_, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-title.function_, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-section, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-section { + color: #268bd2; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-type, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-type, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-template-tag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-template-tag, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .diff .hljs-meta, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .diff .hljs-meta, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword { + color: #6c71c4; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-emphasis, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-emphasis { + color: #6c71c4; + font-style: italic; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-meta, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-meta, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-meta .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-meta .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-meta .hljs-string, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-meta .hljs-string { + color: #d33682; +} +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-meta .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-meta .hljs-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal pre .hljs-meta-keyword, +.book.color-theme-1 .book-body .page-wrapper .page-inner section.normal code .hljs-meta-keyword { + font-weight: bold; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code { + /* From highlight.js@11.10.0/styles/tomorrow-night-bright.css */ + /* Tomorrow Night Bright Theme */ + /* Original theme - https://github.com/chriskempson/tomorrow-theme */ + /* http://jmblog.github.com/color-themes-for-google-code-highlightjs */ + /* Tomorrow Comment */ + /* Tomorrow Red */ + /* Tomorrow Orange */ + /* Tomorrow Yellow */ + /* Tomorrow Green */ + /* Tomorrow Blue */ + /* Tomorrow Purple */ +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre pre code.hljs, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre code.hljs, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code code.hljs { + padding: 3px 5px; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-comment, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-comment, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-quote, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-quote { + color: #969896; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-variable, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-variable, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-template-variable, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-template-variable, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-tag, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-tag, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-name, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-name, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-selector-id, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-selector-id, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-selector-class, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-selector-class, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-regexp, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-regexp, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-deletion, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-deletion { + color: #d54e53; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-number, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-number, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-built_in, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-built_in, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-literal, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-literal, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-type, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-type, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-params, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-params, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-meta, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-meta, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-link, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-link { + color: #e78c45; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-attribute, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-attribute { + color: #e7c547; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-string, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-string, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-symbol, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-symbol, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-bullet, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-bullet, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-addition, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-addition { + color: #b9ca4a; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-title, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-section, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-section { + color: #7aa6da; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-keyword, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-keyword, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-selector-tag, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-selector-tag { + color: #c397d8; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs { + background: black; + color: #eaeaea; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-emphasis, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-emphasis { + font-style: italic; +} +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal pre .hljs-strong, +.book.color-theme-2 .book-body .page-wrapper .page-inner section.normal code .hljs-strong { + font-weight: bold; +} diff --git a/_book/gitbook/fonts/fontawesome/FontAwesome.otf b/_book/gitbook/fonts/fontawesome/FontAwesome.otf new file mode 100644 index 0000000..d4de13e Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/FontAwesome.otf differ diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot new file mode 100644 index 0000000..c7b00d2 Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.eot differ diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg new file mode 100644 index 0000000..8b66187 --- /dev/null +++ b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.svg @@ -0,0 +1,685 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf new file mode 100644 index 0000000..f221e50 Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.ttf differ diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff new file mode 100644 index 0000000..6e7483c Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff differ diff --git a/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 new file mode 100644 index 0000000..7eb74fd Binary files /dev/null and b/_book/gitbook/fonts/fontawesome/fontawesome-webfont.woff2 differ diff --git a/_book/gitbook/gitbook-plugin-livereload/plugin.js b/_book/gitbook/gitbook-plugin-livereload/plugin.js new file mode 100644 index 0000000..923b3ae --- /dev/null +++ b/_book/gitbook/gitbook-plugin-livereload/plugin.js @@ -0,0 +1,11 @@ +(function() { + var newEl = document.createElement('script'), + firstScriptTag = document.getElementsByTagName('script')[0]; + + if (firstScriptTag) { + newEl.async = 1; + newEl.src = '//' + window.location.hostname + ':35729/livereload.js'; + firstScriptTag.parentNode.insertBefore(newEl, firstScriptTag); + } + +})(); diff --git a/_book/gitbook/gitbook-plugin-lunr/lunr.min.js b/_book/gitbook/gitbook-plugin-lunr/lunr.min.js new file mode 100644 index 0000000..6aa6bc7 --- /dev/null +++ b/_book/gitbook/gitbook-plugin-lunr/lunr.min.js @@ -0,0 +1,7 @@ +/** + * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 0.5.12 + * Copyright (C) 2015 Oliver Nightingale + * MIT Licensed + * @license + */ +!function(){var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.5.12",t.utils={},t.utils.warn=function(t){return function(e){t.console&&console.warn&&console.warn(e)}}(this),t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var t=Array.prototype.slice.call(arguments),e=t.pop(),n=t;if("function"!=typeof e)throw new TypeError("last argument must be a function");n.forEach(function(t){this.hasHandler(t)||(this.events[t]=[]),this.events[t].push(e)},this)},t.EventEmitter.prototype.removeListener=function(t,e){if(this.hasHandler(t)){var n=this.events[t].indexOf(e);this.events[t].splice(n,1),this.events[t].length||delete this.events[t]}},t.EventEmitter.prototype.emit=function(t){if(this.hasHandler(t)){var e=Array.prototype.slice.call(arguments,1);this.events[t].forEach(function(t){t.apply(void 0,e)})}},t.EventEmitter.prototype.hasHandler=function(t){return t in this.events},t.tokenizer=function(t){return arguments.length&&null!=t&&void 0!=t?Array.isArray(t)?t.map(function(t){return t.toLowerCase()}):t.toString().trim().toLowerCase().split(/[\s\-]+/):[]},t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.registeredFunctions[e];if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");this._stack.splice(i,0,n)},t.Pipeline.prototype.remove=function(t){var e=this._stack.indexOf(t);-1!=e&&this._stack.splice(e,1)},t.Pipeline.prototype.run=function(t){for(var e=[],n=t.length,i=this._stack.length,o=0;n>o;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;no;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(en.idx?n=n.next:(i+=e.val*n.val,e=e.next,n=n.next);return i},t.Vector.prototype.similarity=function(t){return this.dot(t)/(this.magnitude()*t.magnitude())},t.SortedSet=function(){this.length=0,this.elements=[]},t.SortedSet.load=function(t){var e=new this;return e.elements=t,e.length=t.length,e},t.SortedSet.prototype.add=function(){var t,e;for(t=0;t1;){if(r===t)return o;t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o]}return r===t?o:-1},t.SortedSet.prototype.locationFor=function(t){for(var e=0,n=this.elements.length,i=n-e,o=e+Math.floor(i/2),r=this.elements[o];i>1;)t>r&&(e=o),r>t&&(n=o),i=n-e,o=e+Math.floor(i/2),r=this.elements[o];return r>t?o:t>r?o+1:void 0},t.SortedSet.prototype.intersect=function(e){for(var n=new t.SortedSet,i=0,o=0,r=this.length,s=e.length,a=this.elements,h=e.elements;;){if(i>r-1||o>s-1)break;a[i]!==h[o]?a[i]h[o]&&o++:(n.add(a[i]),i++,o++)}return n},t.SortedSet.prototype.clone=function(){var e=new t.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},t.SortedSet.prototype.union=function(t){var e,n,i;return this.length>=t.length?(e=this,n=t):(e=t,n=this),i=e.clone(),i.add.apply(i,n.toArray()),i},t.SortedSet.prototype.toJSON=function(){return this.toArray()},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.Store,this.tokenStore=new t.TokenStore,this.corpusTokens=new t.SortedSet,this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var t=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,t)},t.Index.prototype.off=function(t,e){return this.eventEmitter.removeListener(t,e)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;return n._fields=e.fields,n._ref=e.ref,n.documentStore=t.Store.load(e.documentStore),n.tokenStore=t.TokenStore.load(e.tokenStore),n.corpusTokens=t.SortedSet.load(e.corpusTokens),n.pipeline=t.Pipeline.load(e.pipeline),n},t.Index.prototype.field=function(t,e){var e=e||{},n={name:t,boost:e.boost||1};return this._fields.push(n),this},t.Index.prototype.ref=function(t){return this._ref=t,this},t.Index.prototype.add=function(e,n){var i={},o=new t.SortedSet,r=e[this._ref],n=void 0===n?!0:n;this._fields.forEach(function(n){var r=this.pipeline.run(t.tokenizer(e[n.name]));i[n.name]=r,t.SortedSet.prototype.add.apply(o,r)},this),this.documentStore.set(r,o),t.SortedSet.prototype.add.apply(this.corpusTokens,o.toArray());for(var s=0;s0&&(i=1+Math.log(this.documentStore.length/n)),this._idfCache[e]=i},t.Index.prototype.search=function(e){var n=this.pipeline.run(t.tokenizer(e)),i=new t.Vector,o=[],r=this._fields.reduce(function(t,e){return t+e.boost},0),s=n.some(function(t){return this.tokenStore.has(t)},this);if(!s)return[];n.forEach(function(e,n,s){var a=1/s.length*this._fields.length*r,h=this,l=this.tokenStore.expand(e).reduce(function(n,o){var r=h.corpusTokens.indexOf(o),s=h.idf(o),l=1,u=new t.SortedSet;if(o!==e){var c=Math.max(3,o.length-e.length);l=1/Math.log(c)}return r>-1&&i.insert(r,a*s*l),Object.keys(h.tokenStore.get(o)).forEach(function(t){u.add(t)}),n.union(u)},new t.SortedSet);o.push(l)},this);var a=o.reduce(function(t,e){return t.intersect(e)});return a.map(function(t){return{ref:t,score:i.similarity(this.documentVector(t))}},this).sort(function(t,e){return e.score-t.score})},t.Index.prototype.documentVector=function(e){for(var n=this.documentStore.get(e),i=n.length,o=new t.Vector,r=0;i>r;r++){var s=n.elements[r],a=this.tokenStore.get(s)[e].tf,h=this.idf(s);o.insert(this.corpusTokens.indexOf(s),a*h)}return o},t.Index.prototype.toJSON=function(){return{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),tokenStore:this.tokenStore.toJSON(),corpusTokens:this.corpusTokens.toJSON(),pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(t){var e=Array.prototype.slice.call(arguments,1);e.unshift(this),t.apply(this,e)},t.Store=function(){this.store={},this.length=0},t.Store.load=function(e){var n=new this;return n.length=e.length,n.store=Object.keys(e.store).reduce(function(n,i){return n[i]=t.SortedSet.load(e.store[i]),n},{}),n},t.Store.prototype.set=function(t,e){this.has(t)||this.length++,this.store[t]=e},t.Store.prototype.get=function(t){return this.store[t]},t.Store.prototype.has=function(t){return t in this.store},t.Store.prototype.remove=function(t){this.has(t)&&(delete this.store[t],this.length--)},t.Store.prototype.toJSON=function(){return{store:this.store,length:this.length}},t.stemmer=function(){var t={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},e={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,a="^("+o+")?"+r+o+"("+r+")?$",h="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,u=new RegExp(s),c=new RegExp(h),f=new RegExp(a),d=new RegExp(l),p=/^(.+?)(ss|i)es$/,m=/^(.+?)([^s])s$/,v=/^(.+?)eed$/,y=/^(.+?)(ed|ing)$/,g=/.$/,S=/(at|bl|iz)$/,w=new RegExp("([^aeiouylsz])\\1$"),x=new RegExp("^"+o+i+"[^aeiouwxy]$"),k=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,_=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,O=/^(.+?)e$/,P=/ll$/,N=new RegExp("^"+o+i+"[^aeiouwxy]$"),T=function(n){var i,o,r,s,a,h,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,a=m,s.test(n)?n=n.replace(s,"$1$2"):a.test(n)&&(n=n.replace(a,"$1$2")),s=v,a=y,s.test(n)){var T=s.exec(n);s=u,s.test(T[1])&&(s=g,n=n.replace(s,""))}else if(a.test(n)){var T=a.exec(n);i=T[1],a=d,a.test(i)&&(n=i,a=S,h=w,l=x,a.test(n)?n+="e":h.test(n)?(s=g,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=k,s.test(n)){var T=s.exec(n);i=T[1],n=i+"i"}if(s=b,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+t[o])}if(s=E,s.test(n)){var T=s.exec(n);i=T[1],o=T[2],s=u,s.test(i)&&(n=i+e[o])}if(s=_,a=F,s.test(n)){var T=s.exec(n);i=T[1],s=c,s.test(i)&&(n=i)}else if(a.test(n)){var T=a.exec(n);i=T[1]+T[2],a=c,a.test(i)&&(n=i)}if(s=O,s.test(n)){var T=s.exec(n);i=T[1],s=c,a=f,h=N,(s.test(i)||a.test(i)&&!h.test(i))&&(n=i)}return s=P,a=c,s.test(n)&&a.test(n)&&(s=g,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return T}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==e?e:void 0},t.stopWordFilter.stopWords={a:"a",able:"able",about:"about",across:"across",after:"after",all:"all",almost:"almost",also:"also",am:"am",among:"among",an:"an",and:"and",any:"any",are:"are",as:"as",at:"at",be:"be",because:"because",been:"been",but:"but",by:"by",can:"can",cannot:"cannot",could:"could",dear:"dear",did:"did","do":"do",does:"does",either:"either","else":"else",ever:"ever",every:"every","for":"for",from:"from",get:"get",got:"got",had:"had",has:"has",have:"have",he:"he",her:"her",hers:"hers",him:"him",his:"his",how:"how",however:"however",i:"i","if":"if","in":"in",into:"into",is:"is",it:"it",its:"its",just:"just",least:"least",let:"let",like:"like",likely:"likely",may:"may",me:"me",might:"might",most:"most",must:"must",my:"my",neither:"neither",no:"no",nor:"nor",not:"not",of:"of",off:"off",often:"often",on:"on",only:"only",or:"or",other:"other",our:"our",own:"own",rather:"rather",said:"said",say:"say",says:"says",she:"she",should:"should",since:"since",so:"so",some:"some",than:"than",that:"that",the:"the",their:"their",them:"them",then:"then",there:"there",these:"these",they:"they","this":"this",tis:"tis",to:"to",too:"too",twas:"twas",us:"us",wants:"wants",was:"was",we:"we",were:"were",what:"what",when:"when",where:"where",which:"which","while":"while",who:"who",whom:"whom",why:"why",will:"will","with":"with",would:"would",yet:"yet",you:"you",your:"your"},t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(t){var e=t.replace(/^\W+/,"").replace(/\W+$/,"");return""===e?void 0:e},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.TokenStore=function(){this.root={docs:{}},this.length=0},t.TokenStore.load=function(t){var e=new this;return e.root=t.root,e.length=t.length,e},t.TokenStore.prototype.add=function(t,e,n){var n=n||this.root,i=t[0],o=t.slice(1);return i in n||(n[i]={docs:{}}),0===o.length?(n[i].docs[e.ref]=e,void(this.length+=1)):this.add(o,e,n[i])},t.TokenStore.prototype.has=function(t){if(!t)return!1;for(var e=this.root,n=0;n element for each result + res.results.forEach(function(res) { + var $li = $('
                                  • ', { + 'class': 'search-results-item' + }); + + var $title = $('

                                    '); + + var $link = $('', { + 'href': gitbook.state.basePath + '/' + res.url, + 'text': res.title + }); + + var content = res.body.trim(); + if (content.length > MAX_DESCRIPTION_SIZE) { + content = content.slice(0, MAX_DESCRIPTION_SIZE).trim()+'...'; + } + var $content = $('

                                    ').html(content); + + $link.appendTo($title); + $title.appendTo($li); + $content.appendTo($li); + $li.appendTo($searchList); + }); + } + + function launchSearch(q) { + // Add class for loading + $body.addClass('with-search'); + $body.addClass('search-loading'); + + // Launch search query + throttle(gitbook.search.query(q, 0, MAX_RESULTS) + .then(function(results) { + displayResults(results); + }) + .always(function() { + $body.removeClass('search-loading'); + }), 1000); + } + + function closeSearch() { + $body.removeClass('with-search'); + $bookSearchResults.removeClass('open'); + } + + function launchSearchFromQueryString() { + var q = getParameterByName('q'); + if (q && q.length > 0) { + // Update search input + $searchInput.val(q); + + // Launch search + launchSearch(q); + } + } + + function bindSearch() { + // Bind DOM + $searchInput = $('#book-search-input input'); + $bookSearchResults = $('#book-search-results'); + $searchList = $bookSearchResults.find('.search-results-list'); + $searchTitle = $bookSearchResults.find('.search-results-title'); + $searchResultsCount = $searchTitle.find('.search-results-count'); + $searchQuery = $searchTitle.find('.search-query'); + + // Launch query based on input content + function handleUpdate() { + var q = $searchInput.val(); + + if (q.length == 0) { + closeSearch(); + } + else { + launchSearch(q); + } + } + + // Detect true content change in search input + // Workaround for IE < 9 + var propertyChangeUnbound = false; + $searchInput.on('propertychange', function(e) { + if (e.originalEvent.propertyName == 'value') { + handleUpdate(); + } + }); + + // HTML5 (IE9 & others) + $searchInput.on('input', function(e) { + // Unbind propertychange event for IE9+ + if (!propertyChangeUnbound) { + $(this).unbind('propertychange'); + propertyChangeUnbound = true; + } + + handleUpdate(); + }); + + // Push to history on blur + $searchInput.on('blur', function(e) { + // Update history state + if (usePushState) { + var uri = updateQueryString('q', $(this).val()); + history.pushState({ path: uri }, null, uri); + } + }); + } + + gitbook.events.on('page.change', function() { + bindSearch(); + closeSearch(); + + // Launch search based on query parameter + if (gitbook.search.isInitialized()) { + launchSearchFromQueryString(); + } + }); + + gitbook.events.on('search.ready', function() { + bindSearch(); + + // Launch search from query param at start + launchSearchFromQueryString(); + }); + + function getParameterByName(name) { + var url = window.location.href; + name = name.replace(/[\[\]]/g, '\\$&'); + var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)', 'i'), + results = regex.exec(url); + if (!results) return null; + if (!results[2]) return ''; + return decodeURIComponent(results[2].replace(/\+/g, ' ')); + } + + function updateQueryString(key, value) { + value = encodeURIComponent(value); + + var url = window.location.href; + var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'), + hash; + + if (re.test(url)) { + if (typeof value !== 'undefined' && value !== null) + return url.replace(re, '$1' + key + '=' + value + '$2$3'); + else { + hash = url.split('#'); + url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, ''); + if (typeof hash[1] !== 'undefined' && hash[1] !== null) + url += '#' + hash[1]; + return url; + } + } + else { + if (typeof value !== 'undefined' && value !== null) { + var separator = url.indexOf('?') !== -1 ? '&' : '?'; + hash = url.split('#'); + url = hash[0] + separator + key + '=' + value; + if (typeof hash[1] !== 'undefined' && hash[1] !== null) + url += '#' + hash[1]; + return url; + } + else + return url; + } + } +}); diff --git a/_book/gitbook/gitbook.js b/_book/gitbook/gitbook.js new file mode 100644 index 0000000..c4f75d1 --- /dev/null +++ b/_book/gitbook/gitbook.js @@ -0,0 +1 @@ +!function r(o,i,a){function s(t,e){if(!i[t]){if(!o[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(l)return l(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}n=i[t]={exports:{}},o[t][0].call(n.exports,function(e){return s(o[t][1][e]||e)},n,n.exports,r,o,i,a)}return i[t].exports}for(var l="function"==typeof require&&require,e=0;e=n.length?(l=!!(f=w(i,c)))&&"get"in f&&!("originalValue"in f.get)?f.get:i[c]:(l=L(i,c),i[c]),l&&!a&&(D[u]=i)}}return i}},{"call-bind-apply-helpers/functionApply":3,"call-bind-apply-helpers/functionCall":4,"es-define-property":9,"es-errors":11,"es-errors/eval":10,"es-errors/range":12,"es-errors/ref":13,"es-errors/syntax":14,"es-errors/type":15,"es-errors/uri":16,"es-object-atoms":17,"function-bind":19,"get-proto":23,"get-proto/Object.getPrototypeOf":21,"get-proto/Reflect.getPrototypeOf":22,gopd:25,"has-symbols":26,hasown:28,"math-intrinsics/abs":30,"math-intrinsics/floor":31,"math-intrinsics/max":33,"math-intrinsics/min":34,"math-intrinsics/pow":35,"math-intrinsics/round":36,"math-intrinsics/sign":37}],21:[function(e,t,n){"use strict";e=e("es-object-atoms");t.exports=e.getPrototypeOf||null},{"es-object-atoms":17}],22:[function(e,t,n){"use strict";t.exports="undefined"!=typeof Reflect&&Reflect.getPrototypeOf||null},{}],23:[function(e,t,n){"use strict";var r=e("./Reflect.getPrototypeOf"),o=e("./Object.getPrototypeOf"),i=e("dunder-proto/get");t.exports=r?function(e){return r(e)}:o?function(e){if(!e||"object"!=typeof e&&"function"!=typeof e)throw new TypeError("getProto: not an object");return o(e)}:i?function(e){return i(e)}:null},{"./Object.getPrototypeOf":21,"./Reflect.getPrototypeOf":22,"dunder-proto/get":8}],24:[function(e,t,n){"use strict";t.exports=Object.getOwnPropertyDescriptor},{}],25:[function(t,e,n){"use strict";t=t("./gOPD");if(t)try{t([],"length")}catch(e){t=null}e.exports=t},{"./gOPD":24}],26:[function(e,t,n){"use strict";var r="undefined"!=typeof Symbol&&Symbol,o=e("./shams");t.exports=function(){return"function"==typeof r&&("function"==typeof Symbol&&("symbol"==typeof r("foo")&&("symbol"==typeof Symbol("bar")&&o())))}},{"./shams":27}],27:[function(e,t,n){"use strict";t.exports=function(){if("function"!=typeof Symbol||"function"!=typeof Object.getOwnPropertySymbols)return!1;if("symbol"!=typeof Symbol.iterator){var e={},t=Symbol("test"),n=Object(t);if("string"==typeof t)return!1;if("[object Symbol]"!==Object.prototype.toString.call(t))return!1;if("[object Symbol]"!==Object.prototype.toString.call(n))return!1;for(var r in e[t]=42,e)return!1;if("function"==typeof Object.keys&&0!==Object.keys(e).length)return!1;if("function"==typeof Object.getOwnPropertyNames&&0!==Object.getOwnPropertyNames(e).length)return!1;n=Object.getOwnPropertySymbols(e);if(1!==n.length||n[0]!==t)return!1;if(!Object.prototype.propertyIsEnumerable.call(e,t))return!1;if("function"==typeof Object.getOwnPropertyDescriptor){n=Object.getOwnPropertyDescriptor(e,t);if(42!==n.value||!0!==n.enumerable)return!1}}return!0}},{}],28:[function(e,t,n){"use strict";var r=Function.prototype.call,o=Object.prototype.hasOwnProperty,e=e("function-bind");t.exports=e.call(r,o)},{"function-bind":19}],29:[function(e,n,t){!function(e,t){"use strict";"object"==typeof n&&"object"==typeof n.exports?n.exports=e.document?t(e,!0):function(e){if(e.document)return t(e);throw new Error("jQuery requires a window with a document")}:t(e)}("undefined"!=typeof window?window:this,function(w,I){"use strict";function v(e){return"function"==typeof e&&"number"!=typeof e.nodeType}function y(e){return null!=e&&e===e.window}var t=[],M=Object.getPrototypeOf,s=t.slice,_=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},F=t.push,H=t.indexOf,W={},B=W.toString,$=W.hasOwnProperty,U=$.toString,z=U.call(Object),g={},A=w.document,G={type:!0,src:!0,nonce:!0,noModule:!0};function V(e,t,n){var r,o,i=(n=n||A).createElement("script");if(i.text=e,t)for(r in G)(o=t[r]||t.getAttribute&&t.getAttribute(r))&&i.setAttribute(r,o);n.head.appendChild(i).parentNode.removeChild(i)}function d(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?W[B.call(e)]||"object":typeof e}var S=function(e,t){return new S.fn.init(e,t)};function K(e){var t=!!e&&"length"in e&&e.length,n=d(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0>10|55296,1023&e|56320))}function M(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e}function _(){A()}var e,p,x,i,F,h,H,W,w,l,c,A,S,n,j,d,r,o,y,T="sizzle"+ +new Date,u=I.document,E=0,B=0,$=N(),U=N(),z=N(),g=N(),G=function(e,t){return e===t&&(c=!0),0},V={}.hasOwnProperty,t=[],K=t.pop,X=t.push,C=t.push,Q=t.slice,v=function(e,t){for(var n=0,r=e.length;n+~]|"+a+")"+a+"*"),re=new RegExp(a+"|>"),oe=new RegExp(Z),ie=new RegExp("^"+s+"$"),b={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),TAG:new RegExp("^("+s+"|[*])"),ATTR:new RegExp("^"+Y),PSEUDO:new RegExp("^"+Z),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+a+"*(even|odd|(([+-]|)(\\d*)n|)"+a+"*(?:([+-]|)"+a+"*(\\d+)|))"+a+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+a+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+a+"*((?:-\\d)?\\d*)"+a+"*\\)|)(?=[^-]|$)","i")},ae=/HTML$/i,se=/^(?:input|select|textarea|button)$/i,le=/^h\d$/i,O=/^[^{]+\{\s*\[native \w/,ce=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ue=/[+~]/,k=new RegExp("\\\\[\\da-fA-F]{1,6}"+a+"?|\\\\([^\\r\\n\\f])","g"),fe=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,pe=ve(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{C.apply(t=Q.call(u.childNodes),u.childNodes),t[u.childNodes.length].nodeType}catch(e){C={apply:t.length?function(e,t){X.apply(e,Q.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function D(t,e,n,r){var o,i,a,s,l,c,u=e&&e.ownerDocument,f=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==f&&9!==f&&11!==f)return n;if(!r&&(A(e),e=e||S,j)){if(11!==f&&(s=ce.exec(t)))if(o=s[1]){if(9===f){if(!(c=e.getElementById(o)))return n;if(c.id===o)return n.push(c),n}else if(u&&(c=u.getElementById(o))&&y(e,c)&&c.id===o)return n.push(c),n}else{if(s[2])return C.apply(n,e.getElementsByTagName(t)),n;if((o=s[3])&&p.getElementsByClassName&&e.getElementsByClassName)return C.apply(n,e.getElementsByClassName(o)),n}if(p.qsa&&!g[t+" "]&&(!d||!d.test(t))&&(1!==f||"object"!==e.nodeName.toLowerCase())){if(c=t,u=e,1===f&&(re.test(t)||ne.test(t))){for((u=ue.test(t)&&ge(e.parentNode)||e)===e&&p.scope||((a=e.getAttribute("id"))?a=a.replace(fe,M):e.setAttribute("id",a=T)),i=(l=h(t)).length;i--;)l[i]=(a?"#"+a:":scope")+" "+R(l[i]);c=l.join(",")}try{return C.apply(n,u.querySelectorAll(c)),n}catch(e){g(t,!0)}finally{a===T&&e.removeAttribute("id")}}}return W(t.replace(m,"$1"),e,n,r)}function N(){var n=[];function r(e,t){return n.push(e+" ")>x.cacheLength&&delete r[n.shift()],r[e+" "]=t}return r}function P(e){return e[T]=!0,e}function L(e){var t=S.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}function he(e,t){for(var n=e.split("|"),r=n.length;r--;)x.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function ye(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&pe(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function q(a){return P(function(i){return i=+i,P(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in p=D.support={},F=D.isXML=function(e){var t=e.namespaceURI,e=(e.ownerDocument||e).documentElement;return!ae.test(t||e&&e.nodeName||"HTML")},A=D.setDocument=function(e){var e=e?e.ownerDocument||e:u;return e!=S&&9===e.nodeType&&e.documentElement&&(n=(S=e).documentElement,j=!F(S),u!=S&&(e=S.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",_,!1):e.attachEvent&&e.attachEvent("onunload",_)),p.scope=L(function(e){return n.appendChild(e).appendChild(S.createElement("div")),void 0!==e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),p.attributes=L(function(e){return e.className="i",!e.getAttribute("className")}),p.getElementsByTagName=L(function(e){return e.appendChild(S.createComment("")),!e.getElementsByTagName("*").length}),p.getElementsByClassName=O.test(S.getElementsByClassName),p.getById=L(function(e){return n.appendChild(e).id=T,!S.getElementsByName||!S.getElementsByName(T).length}),p.getById?(x.filter.ID=function(e){var t=e.replace(k,f);return function(e){return e.getAttribute("id")===t}},x.find.ID=function(e,t){if(void 0!==t.getElementById&&j)return(t=t.getElementById(e))?[t]:[]}):(x.filter.ID=function(e){var t=e.replace(k,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return e&&e.value===t}},x.find.ID=function(e,t){if(void 0!==t.getElementById&&j){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode("id"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode("id"))&&n.value===e)return[i]}return[]}}),x.find.TAG=p.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if("*"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},x.find.CLASS=p.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&j)return t.getElementsByClassName(e)},r=[],d=[],(p.qsa=O.test(S.querySelectorAll))&&(L(function(e){var t;n.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&d.push("[*^$]="+a+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||d.push("\\["+a+"*(?:value|"+J+")"),e.querySelectorAll("[id~="+T+"-]").length||d.push("~="),(t=S.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+a+"*name"+a+"*="+a+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||d.push(":checked"),e.querySelectorAll("a#"+T+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll("\\\f"),d.push("[\\r\\n\\f]")}),L(function(e){e.innerHTML="";var t=S.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&d.push("name"+a+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&d.push(":enabled",":disabled"),n.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(p.matchesSelector=O.test(o=n.matches||n.webkitMatchesSelector||n.mozMatchesSelector||n.oMatchesSelector||n.msMatchesSelector))&&L(function(e){p.disconnectedMatch=o.call(e,"*"),o.call(e,"[s!='']:x"),r.push("!=",Z)}),d=d.length&&new RegExp(d.join("|")),r=r.length&&new RegExp(r.join("|")),e=O.test(n.compareDocumentPosition),y=e||O.test(n.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},G=e?function(e,t){var n;return e===t?(c=!0,0):(n=!e.compareDocumentPosition-!t.compareDocumentPosition)||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e==S||e.ownerDocument==u&&y(u,e)?-1:t==S||t.ownerDocument==u&&y(u,t)?1:l?v(l,e)-v(l,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==S?-1:t==S?1:o?-1:i?1:l?v(l,e)-v(l,t):0;if(o===i)return de(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?de(a[r],s[r]):a[r]==u?-1:s[r]==u?1:0}),S},D.matches=function(e,t){return D(e,null,null,t)},D.matchesSelector=function(e,t){if(A(e),p.matchesSelector&&j&&!g[t+" "]&&(!r||!r.test(t))&&(!d||!d.test(t)))try{var n=o.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){g(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(k,f),e[3]=(e[3]||e[4]||e[5]||"").replace(k,f),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||D.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&D.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return b.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&oe.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(k,f).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+a+")"+e+"("+a+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(t,n,r){return function(e){e=D.attr(e,t);return null==e?"!="===n:!n||(e+="","="===n?e===r:"!="===n?e!==r:"^="===n?r&&0===e.indexOf(r):"*="===n?r&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function Y(e,n,r){return v(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/,te=((S.fn.init=function(e,t,n){if(e){if(n=n||Z,"string"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this);if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:ee.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:A,!0)),J.test(r[1])&&S.isPlainObject(t))for(var r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r])}else(n=A.getElementById(r[2]))&&(this[0]=n,this.length=1)}return this}).prototype=S.fn,Z=S(A),/^(?:parents|prev(?:Until|All))/),ne={children:!0,contents:!0,next:!0,prev:!0};function re(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Se=/^$|^module$|\/(?:java|ecma)script/i,O=(P=A.createDocumentFragment().appendChild(A.createElement("div")),(a=A.createElement("input")).setAttribute("type","radio"),a.setAttribute("checked","checked"),a.setAttribute("name","t"),P.appendChild(a),g.checkClone=P.cloneNode(!0).cloneNode(!0).lastChild.checked,P.innerHTML="",g.noCloneChecked=!!P.cloneNode(!0).lastChild.defaultValue,P.innerHTML="",g.option=!!P.lastChild,{thead:[1,"","
                                    "],col:[2,"","
                                    "],tr:[2,"","
                                    "],td:[3,"","
                                    "],_default:[0,"",""]});function k(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||"*"):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[];return void 0===t||t&&l(e,t)?S.merge([e],n):n}function je(e,t){for(var n=0,r=e.length;n",""]);var Te=/<|&#?\w+;/;function Ee(e,t,n,r,o){for(var i,a,s,l,c,u=t.createDocumentFragment(),f=[],p=0,h=e.length;p\s*$/g;function Ie(e,t){return l(e,"table")&&l(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Me(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function _e(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,o,i;if(1===t.nodeType){if(x.hasData(e)&&(i=x.get(e).events))for(o in x.remove(t,"handle events"),i)for(n=0,r=i[o].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",o=function(e){r.remove(),o=null,e&&t("error"===e.type?404:200,e.type)}),A.head.appendChild(r[0])},abort:function(){o&&o()}}}),[]),Jt=/(=)\?(?=&|$)|\?\?/,Yt=(S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Qt.pop()||S.expando+"_"+kt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Jt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Jt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Jt,"$1"+r):!1!==e.jsonp&&(e.url+=(Dt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return i||S.error(r+" was not called"),i[0]},e.dataTypes[0]="json",o=w[r],w[r]=function(){i=arguments},n.always(function(){void 0===o?S(w).removeProp(r):w[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Qt.push(r)),i&&v(o)&&o(i[0]),i=o=void 0}),"script"}),g.createHTMLDocument=((e=A.implementation.createHTMLDocument("").body).innerHTML="

                                    ",2===e.childNodes.length),S.parseHTML=function(e,t,n){var r;return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(g.createHTMLDocument?((r=(t=A.implementation.createHTMLDocument("")).createElement("base")).href=A.location.href,t.head.appendChild(r)):t=A),r=!n&&[],(n=J.exec(e))?[t.createElement(n[1])]:(n=Ee([e],t,r),r&&r.length&&S(r).remove(),S.merge([],n.childNodes)))},S.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,o,i,a,s=S.css(e,"position"),l=S(e),c={};"static"===s&&(e.style.position="relative"),i=l.offset(),r=S.css(e,"top"),a=S.css(e,"left"),s=("absolute"===s||"fixed"===s)&&-1<(r+a).indexOf("auto")?(o=(s=l.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),null!=(t=v(t)?t.call(e,n,S.extend({},i)):t).top&&(c.top=t.top-i.top+o),null!=t.left&&(c.left=t.left-i.left+s),"using"in t?t.using.call(e,c):("number"==typeof c.top&&(c.top+="px"),"number"==typeof c.left&&(c.left+="px"),l.css(c))}},S.fn.extend({offset:function(t){var e,n;return arguments.length?void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)}):(n=this[0])?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],o={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),o.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-o.top-S.css(r,"marginTop",!0),left:t.left-o.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&"static"===S.css(e,"position");)e=e.offsetParent;return e||T})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,o){var i="pageYOffset"===o;S.fn[t]=function(e){return f(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[o]:e[t];r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=tt(g.pixelPosition,function(e,t){if(t)return t=et(e,n),Qe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,i){S.fn[i]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),o=r||(!0===e||!0===t?"margin":"border");return f(this,function(e,t,n){var r;return y(e)?0===i.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,o):S.style(e,t,n,o)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 0, or `null`');if(U(a,"numericSeparator")&&"boolean"!=typeof a.numericSeparator)throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');var t=a.numericSeparator;if(void 0===n)return"undefined";if(null===n)return"null";if("boolean"==typeof n)return n?"true":"false";if("string"==typeof n)return function e(t,n){if(t.length>n.maxStringLength)return r=t.length-n.maxStringLength,r="... "+r+" more character"+(1"}if($(n))return 0===n.length?"[]":(l=X(n,y),d&&!function(e){for(var t=0;t "+y(e,n))}),ie("Map",b.call(n),c,d)):function(e){if(w&&e&&"object"==typeof e)try{w.call(e);try{b.call(e)}catch(e){return 1}return e instanceof Set}catch(e){}return}(n)?(u=[],A&&A.call(n,function(e){u.push(y(e,n))}),ie("Set",w.call(n),u,d)):function(e){if(S&&e&&"object"==typeof e)try{S.call(e,S);try{j.call(e,j)}catch(e){return 1}return e instanceof WeakMap}catch(e){}return}(n)?V("WeakMap"):function(e){if(j&&e&&"object"==typeof e)try{j.call(e,j);try{S.call(e,S)}catch(e){return 1}return e instanceof WeakSet}catch(e){}return}(n)?V("WeakSet"):function(e){if(T&&e&&"object"==typeof e)try{return T.call(e),1}catch(e){}return}(n)?V("WeakRef"):"[object Number]"===z(f=n)&&B(f)?G(y(Number(n))):function(e){if(e&&"object"==typeof e&&N)try{return N.call(e),1}catch(e){}return}(n)?G(y(N.call(n))):"[object Boolean]"===z(t=n)&&B(t)?G(Q.call(n)):"[object String]"===z(e=n)&&B(e)?G(y(String(n))):"undefined"!=typeof window&&n===window?"{ [object Window] }":"undefined"!=typeof globalThis&&n===globalThis||void 0!==ae&&n===ae?"{ [object globalThis] }":"[object Date]"===z(t=n)&&B(t)||te(n)?String(n):(e=X(n,y),t=I?I(n)===Object.prototype:n instanceof Object||n.constructor===Object,p=n instanceof Object?"":"null prototype",h=!t&&q&&Object(n)===n&&q in n?E.call(z(n),8,-1):p?"Object":"",t=(!t&&"function"==typeof n.constructor&&n.constructor.name?n.constructor.name+" ":"")+(h||p?"["+D.call(k.call([],h||[],p||[]),": ")+"] ":""),0===e.length?t+"{}":d?t+"{"+K(e,d)+"}":t+"{ "+D.call(e,", ")+" }")};var i=Object.prototype.hasOwnProperty||function(e){return e in this};function U(e,t){return i.call(e,t)}function z(e){return n.call(e)}function re(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0,r=e.length;n= 0x80 (not a basic code point)","invalid-input":"Invalid input"},p=m-1,b=Math.floor,x=String.fromCharCode;function w(e){throw new RangeError(f[e])}function h(e,t){for(var n=e.length,r=[];n--;)r[n]=t(e[n]);return r}function d(e,t){var n=e.split("@"),r="",n=(1>>10&1023|55296),e=56320|1023&e),t+=x(e)}).join("")}function S(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function j(e,t,n){var r=0;for(e=n?b(e/s):e>>1,e+=b(e/t);p*v>>1b((g-u)/i))&&w("overflow"),u+=s*i,!(s<(s=a<=p?1:p+v<=a?v:a-p));a+=m)i>b(g/(s=m-s))&&w("overflow"),i*=s;p=j(u-o,t=l.length+1,0==o),b(u/t)>g-f&&w("overflow"),f+=b(u/t),u%=t,l.splice(u++,0,f)}return y(l)}function E(e){for(var t,n,r,o,i,a,s,l,c,u,f=[],p=(e=A(e)).length,h=128,d=72,y=t=0;yb((g-t)/(l=n+1))&&w("overflow"),t+=(o-h)*l,h=o,y=0;yg&&w("overflow"),s==h){for(i=t,a=m;!(i<(c=a<=d?1:d+v<=a?v:a-d));a+=m)f.push(x(S(c+(u=i-c)%(c=m-c),0))),i=b(u/c);f.push(x(S(i,0))),d=j(t,l,n==r),t=0,++n}++t,++h}return f.join("")}if(o={version:"1.4.1",ucs2:{decode:A,encode:y},decode:T,encode:E,toASCII:function(e){return d(e,function(e){return c.test(e)?"xn--"+E(e):e})},toUnicode:function(e){return d(e,function(e){return l.test(e)?T(e.slice(4).toLowerCase()):e})}},"function"==typeof define&&"object"==typeof define.amd&&define.amd)define("punycode",function(){return o});else if(t&&n)if(O.exports==t)n.exports=o;else for(i in o)o.hasOwnProperty(i)&&(t[i]=o[i]);else e.punycode=o}.call(this)}.call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],42:[function(e,t,n){"use strict";var r=String.prototype.replace,o=/%20/g,i="RFC1738",a="RFC3986";t.exports={default:a,formatters:{RFC1738:function(e){return r.call(e,o,"+")},RFC3986:function(e){return String(e)}},RFC1738:i,RFC3986:a}},{}],43:[function(e,t,n){"use strict";var r=e("./stringify"),o=e("./parse"),e=e("./formats");t.exports={formats:e,parse:o,stringify:r}},{"./formats":42,"./parse":44,"./stringify":45}],44:[function(e,t,n){"use strict";function l(e,t){var n={__proto__:null},e=(e=t.ignoreQueryPrefix?e.replace(/^\?/,""):e).replace(/%5B/gi,"[").replace(/%5D/gi,"]"),r=t.parameterLimit===1/0?void 0:t.parameterLimit,o=e.split(t.delimiter,t.throwOnLimitExceeded?r+1:r);if(t.throwOnLimitExceeded&&o.length>r)throw new RangeError("Parameter limit exceeded. Only "+r+" parameter"+(1===r?"":"s")+" allowed.");var i,a=-1,s=t.charset;if(t.charsetSentinel)for(i=0;i=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return e};t.exports=function(e,t){var n=function(e){if(!e)return y;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.decodeDotInKeys&&"boolean"!=typeof e.decodeDotInKeys)throw new TypeError("`decodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");if(void 0!==e.throwOnLimitExceeded&&"boolean"!=typeof e.throwOnLimitExceeded)throw new TypeError("`throwOnLimitExceeded` option must be a boolean");var t=(void 0===e.charset?y:e).charset,n=(void 0===e.duplicates?y:e).duplicates;if("combine"!==n&&"first"!==n&&"last"!==n)throw new TypeError("The duplicates option must be either combine, first, or last");return{allowDots:void 0===e.allowDots?!0===e.decodeDotInKeys||y.allowDots:!!e.allowDots,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:y.allowEmptyArrays,allowPrototypes:("boolean"==typeof e.allowPrototypes?e:y).allowPrototypes,allowSparse:("boolean"==typeof e.allowSparse?e:y).allowSparse,arrayLimit:("number"==typeof e.arrayLimit?e:y).arrayLimit,charset:t,charsetSentinel:("boolean"==typeof e.charsetSentinel?e:y).charsetSentinel,comma:("boolean"==typeof e.comma?e:y).comma,decodeDotInKeys:("boolean"==typeof e.decodeDotInKeys?e:y).decodeDotInKeys,decoder:("function"==typeof e.decoder?e:y).decoder,delimiter:("string"==typeof e.delimiter||p.isRegExp(e.delimiter)?e:y).delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:y.depth,duplicates:n,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:("boolean"==typeof e.interpretNumericEntities?e:y).interpretNumericEntities,parameterLimit:("number"==typeof e.parameterLimit?e:y).parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:("boolean"==typeof e.plainObjects?e:y).plainObjects,strictDepth:"boolean"==typeof e.strictDepth?!!e.strictDepth:y.strictDepth,strictMerge:"boolean"==typeof e.strictMerge?!!e.strictMerge:y.strictMerge,strictNullHandling:("boolean"==typeof e.strictNullHandling?e:y).strictNullHandling,throwOnLimitExceeded:"boolean"==typeof e.throwOnLimitExceeded&&e.throwOnLimitExceeded}}(t);if(""===e||null==e)return n.plainObjects?{__proto__:null}:{};for(var r="string"==typeof e?l(e,n):e,o=n.plainObjects?{__proto__:null}:{},i=Object.keys(r),a=0;an?l(p(o,{plainObjects:r}),o.length-1):o},compact:function(e){for(var t=[{obj:{o:e},prop:"o"}],n=[],r=0;r>6]+g[128|63&f]:f<55296||57344<=f?c[c.length]=g[224|f>>12]+g[128|f>>6&63]+g[128|63&f]:(u+=1,f=65536+((1023&f)<<10|1023&l.charCodeAt(u)),c[c.length]=g[240|f>>18]+g[128|f>>12&63]+g[128|f>>6&63]+g[128|63&f])}a+=c.join("")}return a},isBuffer:function(e){return!(!e||"object"!=typeof e)&&!!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e))},isOverflow:c,isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},markOverflow:l,maybeMap:function(e,t){if(y(e)){for(var n=[],r=0;ra.arrayLimit)return l(p(o.concat(i),a),e);o[e]=i}else{if(!o||"object"!=typeof o)return[o,i];if(c(o)){e=u(o)+1;o[e]=i,f(o,e)}else{if(a&&a.strictMerge)return[o,i];(a&&(a.plainObjects||a.allowPrototypes)||!d.call(Object.prototype,i))&&(o[i]=!0)}}return o}if(o&&"object"==typeof o)return y(e=o)&&!y(i)&&(e=p(o,a)),y(o)&&y(i)?(i.forEach(function(e,t){var n;d.call(o,t)?(n=o[t])&&"object"==typeof n&&e&&"object"==typeof e?o[t]=r(n,e,a):o[o.length]=e:o[t]=e}),o):Object.keys(i).reduce(function(e,t){var n=i[t];return d.call(e,t)?e[t]=r(e[t],n,a):e[t]=n,c(i)&&!c(e)&&l(e,u(i)),c(e)&&(n=parseInt(t,10),String(n)===t&&0<=n&&n>u(e)&&f(e,n)),e},e);if(c(i)){for(var t=Object.keys(i),n=a&&a.plainObjects?{__proto__:null,0:o}:{0:o},s=0;sa.arrayLimit?l(p(e,a),e.length-1):e}}},{"./formats":42,"side-channel":50}],47:[function(e,t,n){"use strict";function i(e,t,n){for(var r,o=e;null!=(r=o.next);o=r)if(r.key===t)return o.next=r.next,n||(r.next=e.next,e.next=r),r}var r=e("object-inspect"),a=e("es-errors/type");t.exports=function(){var o,t={assert:function(e){if(!t.has(e))throw new a("Side channel does not contain "+r(e))},delete:function(e){var t=o&&o.next,e=function(e,t){if(e)return i(e,t,!0)}(o,e);return e&&t&&t===e&&(o=void 0),!!e},get:function(e){var t=o;if(t)return(t=i(t,e))&&t.value},has:function(e){return e=e,!!(t=o)&&!!i(t,e);var t},set:function(e,t){var n,r;t=t,(r=i(n=o=o||{next:void 0},e=e))?r.value=t:n.next={key:e,next:n.next,value:t}}};return t}},{"es-errors/type":15,"object-inspect":38}],48:[function(e,t,n){"use strict";var r=e("get-intrinsic"),o=e("call-bound"),i=e("object-inspect"),a=e("es-errors/type"),s=r("%Map%",!0),l=o("Map.prototype.get",!0),c=o("Map.prototype.set",!0),u=o("Map.prototype.has",!0),f=o("Map.prototype.delete",!0),p=o("Map.prototype.size",!0);t.exports=!!s&&function(){var n,t={assert:function(e){if(!t.has(e))throw new a("Side channel does not contain "+i(e))},delete:function(e){return!!n&&(e=f(n,e),0===p(n)&&(n=void 0),e)},get:function(e){if(n)return l(n,e)},has:function(e){return!!n&&u(n,e)},set:function(e,t){n=n||new s,c(n,e,t)}};return t}},{"call-bound":7,"es-errors/type":15,"get-intrinsic":20,"object-inspect":38}],49:[function(e,t,n){"use strict";var r=e("get-intrinsic"),o=e("call-bound"),i=e("object-inspect"),a=e("side-channel-map"),s=e("es-errors/type"),l=r("%WeakMap%",!0),c=o("WeakMap.prototype.get",!0),u=o("WeakMap.prototype.set",!0),f=o("WeakMap.prototype.has",!0),p=o("WeakMap.prototype.delete",!0);t.exports=l?function(){var n,r,t={assert:function(e){if(!t.has(e))throw new s("Side channel does not contain "+i(e))},delete:function(e){if(l&&e&&("object"==typeof e||"function"==typeof e)){if(n)return p(n,e)}else if(a&&r)return r.delete(e);return!1},get:function(e){return l&&e&&("object"==typeof e||"function"==typeof e)&&n?c(n,e):r&&r.get(e)},has:function(e){return l&&e&&("object"==typeof e||"function"==typeof e)&&n?f(n,e):!!r&&r.has(e)},set:function(e,t){l&&e&&("object"==typeof e||"function"==typeof e)?(n=n||new l,u(n,e,t)):a&&(r=r||a()).set(e,t)}};return t}:a},{"call-bound":7,"es-errors/type":15,"get-intrinsic":20,"object-inspect":38,"side-channel-map":48}],50:[function(e,t,n){"use strict";var r=e("es-errors/type"),o=e("object-inspect"),i=e("side-channel-list"),a=e("side-channel-map"),s=e("side-channel-weakmap")||a||i;t.exports=function(){var n,t={assert:function(e){if(!t.has(e))throw new r("Side channel does not contain "+o(e))},delete:function(e){return!!n&&n.delete(e)},get:function(e){return n&&n.get(e)},has:function(e){return!!n&&n.has(e)},set:function(e,t){(n=n||s()).set(e,t)}};return t}},{"es-errors/type":15,"object-inspect":38,"side-channel-list":47,"side-channel-map":48,"side-channel-weakmap":49}],51:[function(e,t,n){"use strict";var S=e("punycode/");function w(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}var j=/^([a-z0-9.+-]+:)/i,r=/:[0-9]*$/,T=/^(\/\/?(?!\/)[^?\s]*)(\?[^\s]*)?$/,o=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),E=["'"].concat(o),C=["%","/","?",";","#"].concat(E),O=["/","?","#"],k=/^[+a-z0-9A-Z_-]{0,63}$/,D=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,N={javascript:!0,"javascript:":!0},P={javascript:!0,"javascript:":!0},L={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},q=e("qs");function i(e,t,n){var r;return e&&"object"==typeof e&&e instanceof w?e:((r=new w).parse(e,t,n),r)}w.prototype.parse=function(e,t,n){if("string"!=typeof e)throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var r=e.indexOf("?"),r=-1!==r&&rli{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);transform:scale(1,-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-cog:before,.fa-gear:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-repeat:before,.fa-rotate-right:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-cogs:before,.fa-gears:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-floppy-o:before,.fa-save:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-sort:before,.fa-unsorted:before{content:"\f0dc"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-sort-asc:before,.fa-sort-up:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-gavel:before,.fa-legal:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-bolt:before,.fa-flash:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-chain-broken:before,.fa-unlink:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\f150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\f151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\f152"}.fa-eur:before,.fa-euro:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-inr:before,.fa-rupee:before{content:"\f156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\f157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\f158"}.fa-krw:before,.fa-won:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-try:before,.fa-turkish-lira:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\f19c"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\f1c5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\f1c6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:"\f1d0"}.fa-empire:before,.fa-ge:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-paper-plane:before,.fa-send:before{content:"\f1d8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-bed:before,.fa-hotel:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-y-combinator:before,.fa-yc:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-television:before,.fa-tv:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:"\f2a3"}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-sign-language:before,.fa-signing:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}/*! + * Preboot v2 + * git+https://github.com/mdo/preboot.git#4aab4edd85f076d50609cbe28e4fe66cc0771701 + * + * Open sourced under MIT license by @mdo. + * Some variables and mixins from Bootstrap (Apache 2 license). + */.book-langs-index{width:100%;height:100%;padding:40px 0;margin:0;overflow:auto}@media (max-width:600px){.book-langs-index{padding:0}}.book-langs-index .inner{max-width:600px;width:100%;margin:0 auto;padding:30px;background:#fff;border-radius:3px}.book-langs-index .inner h3{margin:0}.book-langs-index .inner .languages{list-style:none;padding:20px 30px;margin-top:20px;border-top:1px solid #eee}.book-langs-index .inner .languages:after,.book-langs-index .inner .languages:before{content:" ";display:table;line-height:0}.book-langs-index .inner .languages:after{clear:both}.book-langs-index .inner .languages li{width:50%;float:left;padding:10px 5px;font-size:16px}@media (max-width:600px){.book-langs-index .inner .languages li{width:100%;max-width:100%}}.book-header{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;overflow:visible;height:50px;padding:0 8px;z-index:2;font-size:.85em;color:#7e888b;background:0 0}.book-header .btn{display:block;height:50px;padding:0 15px;border-bottom:none;color:#ccc;text-transform:uppercase;line-height:50px;-webkit-box-shadow:none!important;box-shadow:none!important;position:relative;font-size:14px}.book-header .btn:hover{position:relative;text-decoration:none;color:#444;background:0 0}.book-header .btn:focus{outline:0}.book-header h1{margin:0;font-size:20px;font-weight:200;text-align:center;line-height:50px;opacity:0;-webkit-transition:opacity ease .4s;-moz-transition:opacity ease .4s;-o-transition:opacity ease .4s;transition:opacity ease .4s;padding-left:200px;padding-right:200px;-webkit-transition:opacity .2s ease;-moz-transition:opacity .2s ease;-o-transition:opacity .2s ease;transition:opacity .2s ease;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.book-header h1 a,.book-header h1 a:hover{color:inherit;text-decoration:none}@media screen and (max-width:1000px){.book-header h1{display:none}}.book-header h1 i{display:none}.book-header:hover h1{opacity:1}.book.is-loading .book-header h1 i{display:inline-block}.book.is-loading .book-header h1 a{display:none}@media print{.book-header{display:none}}.dropdown{position:relative}.dropdown-menu{position:absolute;top:100%;left:0;z-index:100;display:none;float:left;min-width:160px;padding:0;margin:2px 0 0;list-style:none;font-size:14px;background-color:#fafafa;border:1px solid rgba(0,0,0,.07);border-radius:1px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.open{display:block}.dropdown-menu.dropdown-left{left:auto;right:4%}.dropdown-menu.dropdown-left .dropdown-caret{right:14px;left:auto}.dropdown-menu .dropdown-caret{position:absolute;top:-8px;left:14px;width:18px;height:10px;float:left;overflow:hidden}.dropdown-menu .dropdown-caret .caret-outer{position:absolute;border-left:9px solid transparent;border-right:9px solid transparent;border-bottom:9px solid rgba(0,0,0,.1);height:auto;left:0;top:0;width:auto;display:inline-block;margin-left:-1px}.dropdown-menu .dropdown-caret .caret-inner{position:absolute;display:inline-block;margin-top:-1px;top:0;top:1px;border-left:9px solid transparent;border-right:9px solid transparent;border-bottom:9px solid #fafafa}.dropdown-menu .buttons{border-bottom:1px solid rgba(0,0,0,.07)}.dropdown-menu .buttons:after,.dropdown-menu .buttons:before{content:" ";display:table;line-height:0}.dropdown-menu .buttons:after{clear:both}.dropdown-menu .buttons:last-child{border-bottom:none}.dropdown-menu .buttons .button{border:0;background-color:transparent;color:#a6a6a6;width:100%;text-align:center;float:left;line-height:1.42857143;padding:8px 4px}.dropdown-menu .buttons .button:hover{color:#444}.dropdown-menu .buttons .button:focus,.dropdown-menu .buttons .button:hover{outline:0}.dropdown-menu .buttons .button.size-2{width:50%}.dropdown-menu .buttons .button.size-3{width:33%}.book-summary{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;position:absolute;top:0;left:-300px;bottom:0;z-index:1;overflow-y:auto;width:300px;color:#364149;background:#fafafa;border-right:1px solid rgba(0,0,0,.07);-webkit-transition:left 250ms ease;-moz-transition:left 250ms ease;-o-transition:left 250ms ease;transition:left 250ms ease}.book-summary ul.summary{list-style:none;margin:0;padding:0;-webkit-transition:top .5s ease;-moz-transition:top .5s ease;-o-transition:top .5s ease;transition:top .5s ease}.book-summary ul.summary li{list-style:none}.book-summary ul.summary li.header{padding:10px 15px;padding-top:20px;text-transform:uppercase;color:#939da3}.book-summary ul.summary li.divider{height:1px;margin:7px 0;overflow:hidden;background:rgba(0,0,0,.07)}.book-summary ul.summary li i.fa-check{display:none;position:absolute;right:9px;top:16px;font-size:9px;color:#3c3}.book-summary ul.summary li.done>a{color:#364149;font-weight:400}.book-summary ul.summary li.done>a i{display:inline}.book-summary ul.summary li a,.book-summary ul.summary li span{display:block;padding:10px 15px;border-bottom:none;color:#364149;background:0 0;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;position:relative}.book-summary ul.summary li a:hover{text-decoration:underline}.book-summary ul.summary li a:focus{outline:0}.book-summary ul.summary li.active>a{color:#008cff;background:0 0;text-decoration:none}.book-summary ul.summary li ul{padding-left:20px}@media screen and (max-width:600px){.book-summary{width:calc(100% - 60px);bottom:0;left:-100%}}.book.with-summary .book-summary{left:0}.book.without-animation .book-summary{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}@media print{.book-summary{display:none}.book-body{left:0}}.book{position:relative;width:100%;height:100%}@media screen and (min-width:600px){.book.with-summary .book-body{left:300px}}@media screen and (max-width:600px){.book.with-summary{overflow:hidden}.book.with-summary .book-body{-webkit-transform:translate(calc(100% - 60px),0);-moz-transform:translate(calc(100% - 60px),0);-ms-transform:translate(calc(100% - 60px),0);-o-transform:translate(calc(100% - 60px),0);transform:translate(calc(100% - 60px),0)}}.book.without-animation .book-body{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;transition:none!important}.book-body{position:absolute;top:0;right:0;left:0;bottom:0;overflow-y:auto;color:#000;background:#fff;-webkit-transition:left 250ms ease;-moz-transition:left 250ms ease;-o-transition:left 250ms ease;transition:left 250ms ease}.book-body .body-inner{position:absolute;top:0;right:0;left:0;bottom:0;overflow-y:auto}@media screen and (max-width:1240px){.book-body{-webkit-transition:-webkit-transform 250ms ease;-moz-transition:-moz-transform 250ms ease;-o-transition:-o-transform 250ms ease;transition:transform 250ms ease;padding-bottom:20px}.book-body .body-inner{position:static;min-height:calc(100% - 50px)}}.honkit-cloak{display:none}@media print{.book{position:static}.book-body{position:static}.book-body .body-inner{position:static}}.page-wrapper{position:relative;outline:0}.page-inner{position:relative;max-width:800px;margin:0 auto;padding:20px 15px 40px 15px}.page-inner .btn-group .btn{border-radius:0;background:#eee;border:0}.buttons:after,.buttons:before{content:" ";display:table;line-height:0}.buttons:after{clear:both}.button{border:0;background-color:transparent;background:#eee;color:#666;width:100%;text-align:center;float:left;line-height:1.42857143;padding:8px 4px}.button:hover{color:#444}.button:focus,.button:hover{outline:0}.button.size-2{width:50%}.button.size-3{width:33%}.markdown-section{display:block;word-wrap:break-word;overflow:hidden;color:#333;line-height:1.7;text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%}.markdown-section *{box-sizing:border-box;-webkit-box-sizing:border-box;font-size:inherit}.markdown-section>:first-child{margin-top:0!important}.markdown-section>:last-child{margin-bottom:0!important}.markdown-section blockquote,.markdown-section code,.markdown-section figure,.markdown-section img,.markdown-section pre,.markdown-section table,.markdown-section tr{page-break-inside:avoid}.markdown-section h2,.markdown-section h3,.markdown-section h4,.markdown-section h5,.markdown-section p{orphans:3;widows:3}.markdown-section h1,.markdown-section h2,.markdown-section h3,.markdown-section h4,.markdown-section h5{page-break-after:avoid}.markdown-section b,.markdown-section strong{font-weight:700}.markdown-section em{font-style:italic}.markdown-section blockquote,.markdown-section dl,.markdown-section ol,.markdown-section p,.markdown-section table,.markdown-section ul{margin-top:0;margin-bottom:.85em}.markdown-section a{color:#4183c4;text-decoration:none;background:0 0}.markdown-section a:active,.markdown-section a:focus,.markdown-section a:hover{outline:0;text-decoration:underline}.markdown-section img{border:0;max-width:100%}.markdown-section hr{height:4px;padding:0;margin:1.7em 0;overflow:hidden;background-color:#e7e7e7;border:none}.markdown-section hr:after,.markdown-section hr:before{display:table;content:" "}.markdown-section hr:after{clear:both}.markdown-section h1,.markdown-section h2,.markdown-section h3,.markdown-section h4,.markdown-section h5,.markdown-section h6{margin-top:1.275em;margin-bottom:.85em;font-weight:700}.markdown-section h1{font-size:2em}.markdown-section h2{font-size:1.75em}.markdown-section h3{font-size:1.5em}.markdown-section h4{font-size:1.25em}.markdown-section h5{font-size:1em}.markdown-section h6{font-size:1em;color:#777}.markdown-section code,.markdown-section pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;direction:ltr;margin:0;padding:0;border:none;color:inherit}.markdown-section pre{overflow:auto;word-wrap:normal;margin:0;padding:.85em 1em;margin-bottom:1.275em;background:#f7f7f7}.markdown-section pre>code{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;font-size:.85em;white-space:pre;background:0 0}.markdown-section pre>code:after,.markdown-section pre>code:before{content:normal}.markdown-section code{padding:.2em;margin:0;font-size:.85em;background-color:#f7f7f7}.markdown-section code:after,.markdown-section code:before{letter-spacing:-.2em;content:"\00a0"}.markdown-section table{display:table;width:100%;border-collapse:collapse;border-spacing:0;overflow:auto}.markdown-section table td,.markdown-section table th{padding:6px 13px;border:1px solid #ddd}.markdown-section table tr{background-color:#fff;border-top:1px solid #ccc}.markdown-section table tr:nth-child(2n){background-color:#f8f8f8}.markdown-section table th{font-weight:700}.markdown-section ol,.markdown-section ul{padding:0;margin:0;margin-bottom:.85em;padding-left:2em}.markdown-section ol ol,.markdown-section ol ul,.markdown-section ul ol,.markdown-section ul ul{margin-top:0;margin-bottom:0}.markdown-section ol ol{list-style-type:lower-roman}.markdown-section blockquote{margin:0;margin-bottom:.85em;padding:0 15px;color:#858585;border-left:4px solid #e5e5e5}.markdown-section blockquote:first-child{margin-top:0}.markdown-section blockquote:last-child{margin-bottom:0}.markdown-section dl{padding:0}.markdown-section dl dt{padding:0;margin-top:.85em;font-style:italic;font-weight:700}.markdown-section dl dd{padding:0 .85em;margin-bottom:.85em}.markdown-section dd{margin-left:0}.markdown-section .contains-task-list,.markdown-section .task-list{padding:0;padding-left:.8em;list-style:none}.markdown-section .contains-task-list .task-list-item-checkbox,.markdown-section .task-list .task-list-item-checkbox{margin:0 .2em .25em 0;vertical-align:middle}.markdown-section .glossary-term{cursor:help;text-decoration:underline}.navigation{position:absolute;top:50px;bottom:0;margin:0;max-width:150px;min-width:90px;display:flex;justify-content:center;align-content:center;flex-direction:column;font-size:40px;color:#ccc;text-align:center;-webkit-transition:all 350ms ease;-moz-transition:all 350ms ease;-o-transition:all 350ms ease;transition:all 350ms ease}.navigation:hover{text-decoration:none;color:#444}.navigation.navigation-next{right:0}.navigation.navigation-prev{left:0}@media screen and (max-width:1240px){.navigation{position:static;top:auto;max-width:50%;width:50%;display:inline-block;float:left}.navigation.navigation-unique{max-width:100%;width:100%}}@media print{.navigation{display:none}}#book-search-input{padding:6px;background:0 0;transition:top .5s ease;background:#fff;border-bottom:1px solid rgba(0,0,0,.07);border-top:1px solid rgba(0,0,0,.07);margin-bottom:10px;margin-top:-1px}#book-search-input input,#book-search-input input:focus,#book-search-input input:hover{width:100%;background:0 0;border:1px solid transparent;box-shadow:none;outline:0;line-height:22px;padding:7px 7px;color:inherit}#book-search-results{opacity:1}#book-search-results .search-results .search-results-title{text-transform:uppercase;text-align:center;font-weight:200;margin-bottom:35px;opacity:.6}#book-search-results .search-results .has-results .search-results-item{display:block;word-wrap:break-word;overflow:hidden;color:#333;line-height:1.7;text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-moz-text-size-adjust:100%}#book-search-results .search-results .has-results .search-results-item *{box-sizing:border-box;-webkit-box-sizing:border-box;font-size:inherit}#book-search-results .search-results .has-results .search-results-item>:first-child{margin-top:0!important}#book-search-results .search-results .has-results .search-results-item>:last-child{margin-bottom:0!important}#book-search-results .search-results .has-results .search-results-item blockquote,#book-search-results .search-results .has-results .search-results-item code,#book-search-results .search-results .has-results .search-results-item figure,#book-search-results .search-results .has-results .search-results-item img,#book-search-results .search-results .has-results .search-results-item pre,#book-search-results .search-results .has-results .search-results-item table,#book-search-results .search-results .has-results .search-results-item tr{page-break-inside:avoid}#book-search-results .search-results .has-results .search-results-item h2,#book-search-results .search-results .has-results .search-results-item h3,#book-search-results .search-results .has-results .search-results-item h4,#book-search-results .search-results .has-results .search-results-item h5,#book-search-results .search-results .has-results .search-results-item p{orphans:3;widows:3}#book-search-results .search-results .has-results .search-results-item h1,#book-search-results .search-results .has-results .search-results-item h2,#book-search-results .search-results .has-results .search-results-item h3,#book-search-results .search-results .has-results .search-results-item h4,#book-search-results .search-results .has-results .search-results-item h5{page-break-after:avoid}#book-search-results .search-results .has-results .search-results-item b,#book-search-results .search-results .has-results .search-results-item strong{font-weight:700}#book-search-results .search-results .has-results .search-results-item em{font-style:italic}#book-search-results .search-results .has-results .search-results-item blockquote,#book-search-results .search-results .has-results .search-results-item dl,#book-search-results .search-results .has-results .search-results-item ol,#book-search-results .search-results .has-results .search-results-item p,#book-search-results .search-results .has-results .search-results-item table,#book-search-results .search-results .has-results .search-results-item ul{margin-top:0;margin-bottom:.85em}#book-search-results .search-results .has-results .search-results-item a{color:#4183c4;text-decoration:none;background:0 0}#book-search-results .search-results .has-results .search-results-item a:active,#book-search-results .search-results .has-results .search-results-item a:focus,#book-search-results .search-results .has-results .search-results-item a:hover{outline:0;text-decoration:underline}#book-search-results .search-results .has-results .search-results-item img{border:0;max-width:100%}#book-search-results .search-results .has-results .search-results-item hr{height:4px;padding:0;margin:1.7em 0;overflow:hidden;background-color:#e7e7e7;border:none}#book-search-results .search-results .has-results .search-results-item hr:after,#book-search-results .search-results .has-results .search-results-item hr:before{display:table;content:" "}#book-search-results .search-results .has-results .search-results-item hr:after{clear:both}#book-search-results .search-results .has-results .search-results-item h1,#book-search-results .search-results .has-results .search-results-item h2,#book-search-results .search-results .has-results .search-results-item h3,#book-search-results .search-results .has-results .search-results-item h4,#book-search-results .search-results .has-results .search-results-item h5,#book-search-results .search-results .has-results .search-results-item h6{margin-top:1.275em;margin-bottom:.85em;font-weight:700}#book-search-results .search-results .has-results .search-results-item h1{font-size:2em}#book-search-results .search-results .has-results .search-results-item h2{font-size:1.75em}#book-search-results .search-results .has-results .search-results-item h3{font-size:1.5em}#book-search-results .search-results .has-results .search-results-item h4{font-size:1.25em}#book-search-results .search-results .has-results .search-results-item h5{font-size:1em}#book-search-results .search-results .has-results .search-results-item h6{font-size:1em;color:#777}#book-search-results .search-results .has-results .search-results-item code,#book-search-results .search-results .has-results .search-results-item pre{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;direction:ltr;margin:0;padding:0;border:none;color:inherit}#book-search-results .search-results .has-results .search-results-item pre{overflow:auto;word-wrap:normal;margin:0;padding:.85em 1em;margin-bottom:1.275em;background:#f7f7f7}#book-search-results .search-results .has-results .search-results-item pre>code{display:inline;max-width:initial;padding:0;margin:0;overflow:initial;line-height:inherit;font-size:.85em;white-space:pre;background:0 0}#book-search-results .search-results .has-results .search-results-item pre>code:after,#book-search-results .search-results .has-results .search-results-item pre>code:before{content:normal}#book-search-results .search-results .has-results .search-results-item code{padding:.2em;margin:0;font-size:.85em;background-color:#f7f7f7}#book-search-results .search-results .has-results .search-results-item code:after,#book-search-results .search-results .has-results .search-results-item code:before{letter-spacing:-.2em;content:"\00a0"}#book-search-results .search-results .has-results .search-results-item table{display:table;width:100%;border-collapse:collapse;border-spacing:0;overflow:auto}#book-search-results .search-results .has-results .search-results-item table td,#book-search-results .search-results .has-results .search-results-item table th{padding:6px 13px;border:1px solid #ddd}#book-search-results .search-results .has-results .search-results-item table tr{background-color:#fff;border-top:1px solid #ccc}#book-search-results .search-results .has-results .search-results-item table tr:nth-child(2n){background-color:#f8f8f8}#book-search-results .search-results .has-results .search-results-item table th{font-weight:700}#book-search-results .search-results .has-results .search-results-item ol,#book-search-results .search-results .has-results .search-results-item ul{padding:0;margin:0;margin-bottom:.85em;padding-left:2em}#book-search-results .search-results .has-results .search-results-item ol ol,#book-search-results .search-results .has-results .search-results-item ol ul,#book-search-results .search-results .has-results .search-results-item ul ol,#book-search-results .search-results .has-results .search-results-item ul ul{margin-top:0;margin-bottom:0}#book-search-results .search-results .has-results .search-results-item ol ol{list-style-type:lower-roman}#book-search-results .search-results .has-results .search-results-item blockquote{margin:0;margin-bottom:.85em;padding:0 15px;color:#858585;border-left:4px solid #e5e5e5}#book-search-results .search-results .has-results .search-results-item blockquote:first-child{margin-top:0}#book-search-results .search-results .has-results .search-results-item blockquote:last-child{margin-bottom:0}#book-search-results .search-results .has-results .search-results-item dl{padding:0}#book-search-results .search-results .has-results .search-results-item dl dt{padding:0;margin-top:.85em;font-style:italic;font-weight:700}#book-search-results .search-results .has-results .search-results-item dl dd{padding:0 .85em;margin-bottom:.85em}#book-search-results .search-results .has-results .search-results-item dd{margin-left:0}#book-search-results .search-results .has-results .search-results-item .contains-task-list,#book-search-results .search-results .has-results .search-results-item .task-list{padding:0;padding-left:.8em;list-style:none}#book-search-results .search-results .has-results .search-results-item .contains-task-list .task-list-item-checkbox,#book-search-results .search-results .has-results .search-results-item .task-list .task-list-item-checkbox{margin:0 .2em .25em 0;vertical-align:middle}#book-search-results .search-results .has-results .search-results-item h3{margin-top:0;margin-bottom:0}#book-search-results .search-results .no-results{padding:40px 0}body.search-loading #book-search-results{opacity:.3}body.with-search .navigation{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-overflow-scrolling:touch;-webkit-tap-highlight-color:transparent;-webkit-text-size-adjust:none;-webkit-touch-callout:none;-webkit-font-smoothing:antialiased}a{text-decoration:none}body,html{height:100%}html{font-size:62.5%}body{text-rendering:optimizeLegibility;font-smoothing:antialiased;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;letter-spacing:.2px;text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} \ No newline at end of file diff --git a/_book/gitbook/theme.js b/_book/gitbook/theme.js new file mode 100644 index 0000000..01ddb8b --- /dev/null +++ b/_book/gitbook/theme.js @@ -0,0 +1 @@ +!function r(o,i,a){function s(t,e){if(!i[t]){if(!o[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(l)return l(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}n=i[t]={exports:{}},o[t][0].call(n.exports,function(e){return s(o[t][1][e]||e)},n,n.exports,r,o,i,a)}return i[t].exports}for(var l="function"==typeof require&&require,e=0;e=n.length?(l=!!(p=w(i,c)))&&"get"in p&&!("originalValue"in p.get)?p.get:i[c]:(l=L(i,c),i[c]),l&&!a&&(D[u]=i)}}return i}},{"call-bind-apply-helpers/functionApply":3,"call-bind-apply-helpers/functionCall":4,"es-define-property":9,"es-errors":11,"es-errors/eval":10,"es-errors/range":12,"es-errors/ref":13,"es-errors/syntax":14,"es-errors/type":15,"es-errors/uri":16,"es-object-atoms":17,"function-bind":19,"get-proto":23,"get-proto/Object.getPrototypeOf":21,"get-proto/Reflect.getPrototypeOf":22,gopd:25,"has-symbols":26,hasown:28,"math-intrinsics/abs":30,"math-intrinsics/floor":31,"math-intrinsics/max":33,"math-intrinsics/min":34,"math-intrinsics/pow":35,"math-intrinsics/round":36,"math-intrinsics/sign":37}],21:[function(e,t,n){"use strict";e=e("es-object-atoms");t.exports=e.getPrototypeOf||null},{"es-object-atoms":17}],22:[function(e,t,n){"use strict";t.exports="undefined"!=typeof Reflect&&Reflect.getPrototypeOf||null},{}],23:[function(e,t,n){"use strict";var r=e("./Reflect.getPrototypeOf"),o=e("./Object.getPrototypeOf"),i=e("dunder-proto/get");t.exports=r?function(e){return r(e)}:o?function(e){if(!e||"object"!=typeof e&&"function"!=typeof e)throw new TypeError("getProto: not an object");return o(e)}:i?function(e){return i(e)}:null},{"./Object.getPrototypeOf":21,"./Reflect.getPrototypeOf":22,"dunder-proto/get":8}],24:[function(e,t,n){"use strict";t.exports=Object.getOwnPropertyDescriptor},{}],25:[function(t,e,n){"use strict";t=t("./gOPD");if(t)try{t([],"length")}catch(e){t=null}e.exports=t},{"./gOPD":24}],26:[function(e,t,n){"use strict";var r="undefined"!=typeof Symbol&&Symbol,o=e("./shams");t.exports=function(){return"function"==typeof r&&("function"==typeof Symbol&&("symbol"==typeof r("foo")&&("symbol"==typeof Symbol("bar")&&o())))}},{"./shams":27}],27:[function(e,t,n){"use strict";t.exports=function(){if("function"!=typeof Symbol||"function"!=typeof Object.getOwnPropertySymbols)return!1;if("symbol"!=typeof Symbol.iterator){var e={},t=Symbol("test"),n=Object(t);if("string"==typeof t)return!1;if("[object Symbol]"!==Object.prototype.toString.call(t))return!1;if("[object Symbol]"!==Object.prototype.toString.call(n))return!1;for(var r in e[t]=42,e)return!1;if("function"==typeof Object.keys&&0!==Object.keys(e).length)return!1;if("function"==typeof Object.getOwnPropertyNames&&0!==Object.getOwnPropertyNames(e).length)return!1;n=Object.getOwnPropertySymbols(e);if(1!==n.length||n[0]!==t)return!1;if(!Object.prototype.propertyIsEnumerable.call(e,t))return!1;if("function"==typeof Object.getOwnPropertyDescriptor){n=Object.getOwnPropertyDescriptor(e,t);if(42!==n.value||!0!==n.enumerable)return!1}}return!0}},{}],28:[function(e,t,n){"use strict";var r=Function.prototype.call,o=Object.prototype.hasOwnProperty,e=e("function-bind");t.exports=e.call(r,o)},{"function-bind":19}],29:[function(e,n,t){!function(e,t){"use strict";"object"==typeof n&&"object"==typeof n.exports?n.exports=e.document?t(e,!0):function(e){if(e.document)return t(e);throw new Error("jQuery requires a window with a document")}:t(e)}("undefined"!=typeof window?window:this,function(w,I){"use strict";function v(e){return"function"==typeof e&&"number"!=typeof e.nodeType}function y(e){return null!=e&&e===e.window}var t=[],M=Object.getPrototypeOf,s=t.slice,_=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},F=t.push,H=t.indexOf,B={},W=B.toString,$=B.hasOwnProperty,U=$.toString,z=U.call(Object),g={},S=w.document,K={type:!0,src:!0,nonce:!0,noModule:!0};function G(e,t,n){var r,o,i=(n=n||S).createElement("script");if(i.text=e,t)for(r in K)(o=t[r]||t.getAttribute&&t.getAttribute(r))&&i.setAttribute(r,o);n.head.appendChild(i).parentNode.removeChild(i)}function h(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?B[W.call(e)]||"object":typeof e}var A=function(e,t){return new A.fn.init(e,t)};function V(e){var t=!!e&&"length"in e&&e.length,n=h(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0>10|55296,1023&e|56320))}function M(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e}function _(){S()}var e,f,x,i,F,d,H,B,w,l,c,S,A,n,j,h,r,o,y,E="sizzle"+ +new Date,u=I.document,k=0,W=0,$=N(),U=N(),z=N(),g=N(),K=function(e,t){return e===t&&(c=!0),0},G={}.hasOwnProperty,t=[],V=t.pop,X=t.push,T=t.push,Q=t.slice,v=function(e,t){for(var n=0,r=e.length;n+~]|"+a+")"+a+"*"),re=new RegExp(a+"|>"),oe=new RegExp(Z),ie=new RegExp("^"+s+"$"),b={ID:new RegExp("^#("+s+")"),CLASS:new RegExp("^\\.("+s+")"),TAG:new RegExp("^("+s+"|[*])"),ATTR:new RegExp("^"+Y),PSEUDO:new RegExp("^"+Z),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+a+"*(even|odd|(([+-]|)(\\d*)n|)"+a+"*(?:([+-]|)"+a+"*(\\d+)|))"+a+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+a+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+a+"*((?:-\\d)?\\d*)"+a+"*\\)|)(?=[^-]|$)","i")},ae=/HTML$/i,se=/^(?:input|select|textarea|button)$/i,le=/^h\d$/i,C=/^[^{]+\{\s*\[native \w/,ce=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ue=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+a+"?|\\\\([^\\r\\n\\f])","g"),pe=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,fe=ve(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{T.apply(t=Q.call(u.childNodes),u.childNodes),t[u.childNodes.length].nodeType}catch(e){T={apply:t.length?function(e,t){X.apply(e,Q.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function D(t,e,n,r){var o,i,a,s,l,c,u=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(S(e),e=e||A,j)){if(11!==p&&(s=ce.exec(t)))if(o=s[1]){if(9===p){if(!(c=e.getElementById(o)))return n;if(c.id===o)return n.push(c),n}else if(u&&(c=u.getElementById(o))&&y(e,c)&&c.id===o)return n.push(c),n}else{if(s[2])return T.apply(n,e.getElementsByTagName(t)),n;if((o=s[3])&&f.getElementsByClassName&&e.getElementsByClassName)return T.apply(n,e.getElementsByClassName(o)),n}if(f.qsa&&!g[t+" "]&&(!h||!h.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,u=e,1===p&&(re.test(t)||ne.test(t))){for((u=ue.test(t)&&ge(e.parentNode)||e)===e&&f.scope||((a=e.getAttribute("id"))?a=a.replace(pe,M):e.setAttribute("id",a=E)),i=(l=d(t)).length;i--;)l[i]=(a?"#"+a:":scope")+" "+R(l[i]);c=l.join(",")}try{return T.apply(n,u.querySelectorAll(c)),n}catch(e){g(t,!0)}finally{a===E&&e.removeAttribute("id")}}}return B(t.replace(m,"$1"),e,n,r)}function N(){var n=[];function r(e,t){return n.push(e+" ")>x.cacheLength&&delete r[n.shift()],r[e+" "]=t}return r}function P(e){return e[E]=!0,e}function L(e){var t=A.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t)}}function de(e,t){for(var n=e.split("|"),r=n.length;r--;)x.attrHandle[n[r]]=t}function he(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function ye(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&fe(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function q(a){return P(function(i){return i=+i,P(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in f=D.support={},F=D.isXML=function(e){var t=e.namespaceURI,e=(e.ownerDocument||e).documentElement;return!ae.test(t||e&&e.nodeName||"HTML")},S=D.setDocument=function(e){var e=e?e.ownerDocument||e:u;return e!=A&&9===e.nodeType&&e.documentElement&&(n=(A=e).documentElement,j=!F(A),u!=A&&(e=A.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",_,!1):e.attachEvent&&e.attachEvent("onunload",_)),f.scope=L(function(e){return n.appendChild(e).appendChild(A.createElement("div")),void 0!==e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),f.attributes=L(function(e){return e.className="i",!e.getAttribute("className")}),f.getElementsByTagName=L(function(e){return e.appendChild(A.createComment("")),!e.getElementsByTagName("*").length}),f.getElementsByClassName=C.test(A.getElementsByClassName),f.getById=L(function(e){return n.appendChild(e).id=E,!A.getElementsByName||!A.getElementsByName(E).length}),f.getById?(x.filter.ID=function(e){var t=e.replace(O,p);return function(e){return e.getAttribute("id")===t}},x.find.ID=function(e,t){if(void 0!==t.getElementById&&j)return(t=t.getElementById(e))?[t]:[]}):(x.filter.ID=function(e){var t=e.replace(O,p);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return e&&e.value===t}},x.find.ID=function(e,t){if(void 0!==t.getElementById&&j){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode("id"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode("id"))&&n.value===e)return[i]}return[]}}),x.find.TAG=f.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):f.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if("*"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},x.find.CLASS=f.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&j)return t.getElementsByClassName(e)},r=[],h=[],(f.qsa=C.test(A.querySelectorAll))&&(L(function(e){var t;n.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&h.push("[*^$]="+a+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||h.push("\\["+a+"*(?:value|"+J+")"),e.querySelectorAll("[id~="+E+"-]").length||h.push("~="),(t=A.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||h.push("\\["+a+"*name"+a+"*="+a+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||h.push(":checked"),e.querySelectorAll("a#"+E+"+*").length||h.push(".#.+[+~]"),e.querySelectorAll("\\\f"),h.push("[\\r\\n\\f]")}),L(function(e){e.innerHTML="";var t=A.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&h.push("name"+a+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&h.push(":enabled",":disabled"),n.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(f.matchesSelector=C.test(o=n.matches||n.webkitMatchesSelector||n.mozMatchesSelector||n.oMatchesSelector||n.msMatchesSelector))&&L(function(e){f.disconnectedMatch=o.call(e,"*"),o.call(e,"[s!='']:x"),r.push("!=",Z)}),h=h.length&&new RegExp(h.join("|")),r=r.length&&new RegExp(r.join("|")),e=C.test(n.compareDocumentPosition),y=e||C.test(n.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},K=e?function(e,t){var n;return e===t?(c=!0,0):(n=!e.compareDocumentPosition-!t.compareDocumentPosition)||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!f.sortDetached&&t.compareDocumentPosition(e)===n?e==A||e.ownerDocument==u&&y(u,e)?-1:t==A||t.ownerDocument==u&&y(u,t)?1:l?v(l,e)-v(l,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==A?-1:t==A?1:o?-1:i?1:l?v(l,e)-v(l,t):0;if(o===i)return he(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?he(a[r],s[r]):a[r]==u?-1:s[r]==u?1:0}),A},D.matches=function(e,t){return D(e,null,null,t)},D.matchesSelector=function(e,t){if(S(e),f.matchesSelector&&j&&!g[t+" "]&&(!r||!r.test(t))&&(!h||!h.test(t)))try{var n=o.call(e,t);if(n||f.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){g(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,p),e[3]=(e[3]||e[4]||e[5]||"").replace(O,p),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||D.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&D.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return b.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&oe.test(n)&&(t=d(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,p).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=$[e+" "];return t||(t=new RegExp("(^|"+a+")"+e+"("+a+"|$)"))&&$(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(t,n,r){return function(e){e=D.attr(e,t);return null==e?"!="===n:!n||(e+="","="===n?e===r:"!="===n?e!==r:"^="===n?r&&0===e.indexOf(r):"*="===n?r&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function Y(e,n,r){return v(n)?A.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?A.grep(e,function(e){return e===n!==r}):"string"!=typeof n?A.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/,te=((A.fn.init=function(e,t,n){if(e){if(n=n||Z,"string"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(A):A.makeArray(e,this);if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:ee.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof A?t[0]:t,A.merge(this,A.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:S,!0)),J.test(r[1])&&A.isPlainObject(t))for(var r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r])}else(n=S.getElementById(r[2]))&&(this[0]=n,this.length=1)}return this}).prototype=A.fn,Z=A(S),/^(?:parents|prev(?:Until|All))/),ne={children:!0,contents:!0,next:!0,prev:!0};function re(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}A.fn.extend({has:function(e){var t=A(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ae=/^$|^module$|\/(?:java|ecma)script/i,C=(P=S.createDocumentFragment().appendChild(S.createElement("div")),(a=S.createElement("input")).setAttribute("type","radio"),a.setAttribute("checked","checked"),a.setAttribute("name","t"),P.appendChild(a),g.checkClone=P.cloneNode(!0).cloneNode(!0).lastChild.checked,P.innerHTML="",g.noCloneChecked=!!P.cloneNode(!0).lastChild.defaultValue,P.innerHTML="",g.option=!!P.lastChild,{thead:[1,"","
                                    "],col:[2,"","
                                    "],tr:[2,"","
                                    "],td:[3,"","
                                    "],_default:[0,"",""]});function O(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||"*"):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[];return void 0===t||t&&l(e,t)?A.merge([e],n):n}function je(e,t){for(var n=0,r=e.length;n",""]);var Ee=/<|&#?\w+;/;function ke(e,t,n,r,o){for(var i,a,s,l,c,u=t.createDocumentFragment(),p=[],f=0,d=e.length;f\s*$/g;function Ie(e,t){return l(e,"table")&&l(11!==t.nodeType?t:t.firstChild,"tr")&&A(e).children("tbody")[0]||e}function Me(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function _e(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,o,i;if(1===t.nodeType){if(x.hasData(e)&&(i=x.get(e).events))for(o in x.remove(t,"handle events"),i)for(n=0,r=i[o].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",o=function(e){r.remove(),o=null,e&&t("error"===e.type?404:200,e.type)}),S.head.appendChild(r[0])},abort:function(){o&&o()}}}),[]),Jt=/(=)\?(?=&|$)|\?\?/,Yt=(A.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Qt.pop()||A.expando+"_"+Ot.guid++;return this[e]=!0,e}}),A.ajaxPrefilter("json jsonp",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Jt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Jt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Jt,"$1"+r):!1!==e.jsonp&&(e.url+=(Dt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return i||A.error(r+" was not called"),i[0]},e.dataTypes[0]="json",o=w[r],w[r]=function(){i=arguments},n.always(function(){void 0===o?A(w).removeProp(r):w[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Qt.push(r)),i&&v(o)&&o(i[0]),i=o=void 0}),"script"}),g.createHTMLDocument=((e=S.implementation.createHTMLDocument("").body).innerHTML="
                                    ",2===e.childNodes.length),A.parseHTML=function(e,t,n){var r;return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(g.createHTMLDocument?((r=(t=S.implementation.createHTMLDocument("")).createElement("base")).href=S.location.href,t.head.appendChild(r)):t=S),r=!n&&[],(n=J.exec(e))?[t.createElement(n[1])]:(n=ke([e],t,r),r&&r.length&&A(r).remove(),A.merge([],n.childNodes)))},A.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(" ");return-1").append(A.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},A.expr.pseudos.animated=function(t){return A.grep(A.timers,function(e){return t===e.elem}).length},A.offset={setOffset:function(e,t,n){var r,o,i,a,s=A.css(e,"position"),l=A(e),c={};"static"===s&&(e.style.position="relative"),i=l.offset(),r=A.css(e,"top"),a=A.css(e,"left"),s=("absolute"===s||"fixed"===s)&&-1<(r+a).indexOf("auto")?(o=(s=l.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),null!=(t=v(t)?t.call(e,n,A.extend({},i)):t).top&&(c.top=t.top-i.top+o),null!=t.left&&(c.left=t.left-i.left+s),"using"in t?t.using.call(e,c):("number"==typeof c.top&&(c.top+="px"),"number"==typeof c.left&&(c.left+="px"),l.css(c))}},A.fn.extend({offset:function(t){var e,n;return arguments.length?void 0===t?this:this.each(function(e){A.offset.setOffset(this,t,e)}):(n=this[0])?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],o={top:0,left:0};if("fixed"===A.css(r,"position"))t=r.getBoundingClientRect();else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&"static"===A.css(e,"position");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=A(e).offset()).top+=A.css(e,"borderTopWidth",!0),o.left+=A.css(e,"borderLeftWidth",!0))}return{top:t.top-o.top-A.css(r,"marginTop",!0),left:t.left-o.left-A.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&"static"===A.css(e,"position");)e=e.offsetParent;return e||E})}}),A.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,o){var i="pageYOffset"===o;A.fn[t]=function(e){return p(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[o]:e[t];r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),A.each(["top","left"],function(e,n){A.cssHooks[n]=tt(g.pixelPosition,function(e,t){if(t)return t=et(e,n),Qe.test(t)?A(e).position()[n]+"px":t})}),A.each({Height:"height",Width:"width"},function(a,s){A.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,i){A.fn[i]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),o=r||(!0===e||!0===t?"margin":"border");return p(this,function(e,t,n){var r;return y(e)?0===i.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?A.css(e,t,o):A.style(e,t,n,o)},s,n?e:void 0,n)}})}),A.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){A.fn[t]=function(e){return this.on(t,e)}}),A.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),A.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){A.fn[n]=function(e,t){return 0":".","?":"/","|":"\\"},c={option:"alt",command:"meta",return:"enter",escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},u=1;u<20;++u)a[111+u]="f"+u;for(u=0;u<=9;++u)a[u+96]=u;S.prototype.bind=function(e,t,n){return e=e instanceof Array?e:[e],this._bindMultiple.call(this,e,t,n),this},S.prototype.unbind=function(e,t){return this.bind.call(this,e,function(){},t)},S.prototype.trigger=function(e,t){return this._directMap[e+":"+t]&&this._directMap[e+":"+t]({},e),this},S.prototype.reset=function(){return this._callbacks={},this._directMap={},this},S.prototype.stopCallback=function(e,t){return!(-1<(" "+t.className+" ").indexOf(" mousetrap "))&&(!function e(t,n){return null!==t&&t!==o&&(t===n||e(t.parentNode,n))}(t,this.target)&&("INPUT"==t.tagName||"SELECT"==t.tagName||"TEXTAREA"==t.tagName||t.isContentEditable))},S.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)},S.addKeycodes=function(e){for(var t in e)e.hasOwnProperty(t)&&(a[t]=e[t]);i=null},(S.init=function(){var e,t=S(o);for(e in t)"_"!==e.charAt(0)&&(S[e]=function(e){return function(){return t[e].apply(t,arguments)}}(e))})(),r.Mousetrap=S,void 0!==t&&t.exports&&(t.exports=S),"function"==typeof define&&define.amd&&define(function(){return S})}function v(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)}function b(e){var t;return"keypress"==e.type?(t=String.fromCharCode(e.which),e.shiftKey?t:t.toLowerCase()):a[e.which]||s[e.which]||String.fromCharCode(e.which).toLowerCase()}function x(e){return"shift"==e||"ctrl"==e||"alt"==e||"meta"==e}function p(e,t,n){return n="keypress"==(n=n||(function(){if(!i)for(var e in i={},a)95 0, or `null`');if(U(a,"numericSeparator")&&"boolean"!=typeof a.numericSeparator)throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');var t=a.numericSeparator;if(void 0===n)return"undefined";if(null===n)return"null";if("boolean"==typeof n)return n?"true":"false";if("string"==typeof n)return function e(t,n){if(t.length>n.maxStringLength)return r=t.length-n.maxStringLength,r="... "+r+" more character"+(1"}if($(n))return 0===n.length?"[]":(l=X(n,y),h&&!function(e){for(var t=0;t "+y(e,n))}),ie("Map",b.call(n),c,h)):function(e){if(w&&e&&"object"==typeof e)try{w.call(e);try{b.call(e)}catch(e){return 1}return e instanceof Set}catch(e){}return}(n)?(u=[],S&&S.call(n,function(e){u.push(y(e,n))}),ie("Set",w.call(n),u,h)):function(e){if(A&&e&&"object"==typeof e)try{A.call(e,A);try{j.call(e,j)}catch(e){return 1}return e instanceof WeakMap}catch(e){}return}(n)?G("WeakMap"):function(e){if(j&&e&&"object"==typeof e)try{j.call(e,j);try{A.call(e,A)}catch(e){return 1}return e instanceof WeakSet}catch(e){}return}(n)?G("WeakSet"):function(e){if(E&&e&&"object"==typeof e)try{return E.call(e),1}catch(e){}return}(n)?G("WeakRef"):"[object Number]"===z(p=n)&&W(p)?K(y(Number(n))):function(e){if(e&&"object"==typeof e&&N)try{return N.call(e),1}catch(e){}return}(n)?K(y(N.call(n))):"[object Boolean]"===z(t=n)&&W(t)?K(Q.call(n)):"[object String]"===z(e=n)&&W(e)?K(y(String(n))):"undefined"!=typeof window&&n===window?"{ [object Window] }":"undefined"!=typeof globalThis&&n===globalThis||void 0!==ae&&n===ae?"{ [object globalThis] }":"[object Date]"===z(t=n)&&W(t)||te(n)?String(n):(e=X(n,y),t=I?I(n)===Object.prototype:n instanceof Object||n.constructor===Object,f=n instanceof Object?"":"null prototype",d=!t&&q&&Object(n)===n&&q in n?k.call(z(n),8,-1):f?"Object":"",t=(!t&&"function"==typeof n.constructor&&n.constructor.name?n.constructor.name+" ":"")+(d||f?"["+D.call(O.call([],d||[],f||[]),": ")+"] ":""),0===e.length?t+"{}":h?t+"{"+V(e,h)+"}":t+"{ "+D.call(e,", ")+" }")};var i=Object.prototype.hasOwnProperty||function(e){return e in this};function U(e,t){return i.call(e,t)}function z(e){return n.call(e)}function re(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0,r=e.length;n= 0x80 (not a basic code point)","invalid-input":"Invalid input"},f=m-1,b=Math.floor,x=String.fromCharCode;function w(e){throw new RangeError(p[e])}function d(e,t){for(var n=e.length,r=[];n--;)r[n]=t(e[n]);return r}function h(e,t){var n=e.split("@"),r="",n=(1>>10&1023|55296),e=56320|1023&e),t+=x(e)}).join("")}function A(e,t){return e+22+75*(e<26)-((0!=t)<<5)}function j(e,t,n){var r=0;for(e=n?b(e/s):e>>1,e+=b(e/t);f*v>>1b((g-u)/i))&&w("overflow"),u+=s*i,!(s<(s=a<=f?1:f+v<=a?v:a-f));a+=m)i>b(g/(s=m-s))&&w("overflow"),i*=s;f=j(u-o,t=l.length+1,0==o),b(u/t)>g-p&&w("overflow"),p+=b(u/t),u%=t,l.splice(u++,0,p)}return y(l)}function k(e){for(var t,n,r,o,i,a,s,l,c,u,p=[],f=(e=S(e)).length,d=128,h=72,y=t=0;yb((g-t)/(l=n+1))&&w("overflow"),t+=(o-d)*l,d=o,y=0;yg&&w("overflow"),s==d){for(i=t,a=m;!(i<(c=a<=h?1:h+v<=a?v:a-h));a+=m)p.push(x(A(c+(u=i-c)%(c=m-c),0))),i=b(u/c);p.push(x(A(i,0))),h=j(t,l,n==r),t=0,++n}++t,++d}return p.join("")}if(o={version:"1.4.1",ucs2:{decode:S,encode:y},decode:E,encode:k,toASCII:function(e){return h(e,function(e){return c.test(e)?"xn--"+k(e):e})},toUnicode:function(e){return h(e,function(e){return l.test(e)?E(e.slice(4).toLowerCase()):e})}},"function"==typeof define&&"object"==typeof define.amd&&define.amd)define("punycode",function(){return o});else if(t&&n)if(C.exports==t)n.exports=o;else for(i in o)o.hasOwnProperty(i)&&(t[i]=o[i]);else e.punycode=o}.call(this)}.call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],41:[function(e,t,n){"use strict";var r=String.prototype.replace,o=/%20/g,i="RFC1738",a="RFC3986";t.exports={default:a,formatters:{RFC1738:function(e){return r.call(e,o,"+")},RFC3986:function(e){return String(e)}},RFC1738:i,RFC3986:a}},{}],42:[function(e,t,n){"use strict";var r=e("./stringify"),o=e("./parse"),e=e("./formats");t.exports={formats:e,parse:o,stringify:r}},{"./formats":41,"./parse":43,"./stringify":44}],43:[function(e,t,n){"use strict";function l(e,t){var n={__proto__:null},e=(e=t.ignoreQueryPrefix?e.replace(/^\?/,""):e).replace(/%5B/gi,"[").replace(/%5D/gi,"]"),r=t.parameterLimit===1/0?void 0:t.parameterLimit,o=e.split(t.delimiter,t.throwOnLimitExceeded?r+1:r);if(t.throwOnLimitExceeded&&o.length>r)throw new RangeError("Parameter limit exceeded. Only "+r+" parameter"+(1===r?"":"s")+" allowed.");var i,a=-1,s=t.charset;if(t.charsetSentinel)for(i=0;i=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return e};t.exports=function(e,t){var n=function(e){if(!e)return y;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.decodeDotInKeys&&"boolean"!=typeof e.decodeDotInKeys)throw new TypeError("`decodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");if(void 0!==e.throwOnLimitExceeded&&"boolean"!=typeof e.throwOnLimitExceeded)throw new TypeError("`throwOnLimitExceeded` option must be a boolean");var t=(void 0===e.charset?y:e).charset,n=(void 0===e.duplicates?y:e).duplicates;if("combine"!==n&&"first"!==n&&"last"!==n)throw new TypeError("The duplicates option must be either combine, first, or last");return{allowDots:void 0===e.allowDots?!0===e.decodeDotInKeys||y.allowDots:!!e.allowDots,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:y.allowEmptyArrays,allowPrototypes:("boolean"==typeof e.allowPrototypes?e:y).allowPrototypes,allowSparse:("boolean"==typeof e.allowSparse?e:y).allowSparse,arrayLimit:("number"==typeof e.arrayLimit?e:y).arrayLimit,charset:t,charsetSentinel:("boolean"==typeof e.charsetSentinel?e:y).charsetSentinel,comma:("boolean"==typeof e.comma?e:y).comma,decodeDotInKeys:("boolean"==typeof e.decodeDotInKeys?e:y).decodeDotInKeys,decoder:("function"==typeof e.decoder?e:y).decoder,delimiter:("string"==typeof e.delimiter||f.isRegExp(e.delimiter)?e:y).delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:y.depth,duplicates:n,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:("boolean"==typeof e.interpretNumericEntities?e:y).interpretNumericEntities,parameterLimit:("number"==typeof e.parameterLimit?e:y).parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:("boolean"==typeof e.plainObjects?e:y).plainObjects,strictDepth:"boolean"==typeof e.strictDepth?!!e.strictDepth:y.strictDepth,strictMerge:"boolean"==typeof e.strictMerge?!!e.strictMerge:y.strictMerge,strictNullHandling:("boolean"==typeof e.strictNullHandling?e:y).strictNullHandling,throwOnLimitExceeded:"boolean"==typeof e.throwOnLimitExceeded&&e.throwOnLimitExceeded}}(t);if(""===e||null==e)return n.plainObjects?{__proto__:null}:{};for(var r="string"==typeof e?l(e,n):e,o=n.plainObjects?{__proto__:null}:{},i=Object.keys(r),a=0;an?l(f(o,{plainObjects:r}),o.length-1):o},compact:function(e){for(var t=[{obj:{o:e},prop:"o"}],n=[],r=0;r>6]+g[128|63&p]:p<55296||57344<=p?c[c.length]=g[224|p>>12]+g[128|p>>6&63]+g[128|63&p]:(u+=1,p=65536+((1023&p)<<10|1023&l.charCodeAt(u)),c[c.length]=g[240|p>>18]+g[128|p>>12&63]+g[128|p>>6&63]+g[128|63&p])}a+=c.join("")}return a},isBuffer:function(e){return!(!e||"object"!=typeof e)&&!!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e))},isOverflow:c,isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},markOverflow:l,maybeMap:function(e,t){if(y(e)){for(var n=[],r=0;ra.arrayLimit)return l(f(o.concat(i),a),e);o[e]=i}else{if(!o||"object"!=typeof o)return[o,i];if(c(o)){e=u(o)+1;o[e]=i,p(o,e)}else{if(a&&a.strictMerge)return[o,i];(a&&(a.plainObjects||a.allowPrototypes)||!h.call(Object.prototype,i))&&(o[i]=!0)}}return o}if(o&&"object"==typeof o)return y(e=o)&&!y(i)&&(e=f(o,a)),y(o)&&y(i)?(i.forEach(function(e,t){var n;h.call(o,t)?(n=o[t])&&"object"==typeof n&&e&&"object"==typeof e?o[t]=r(n,e,a):o[o.length]=e:o[t]=e}),o):Object.keys(i).reduce(function(e,t){var n=i[t];return h.call(e,t)?e[t]=r(e[t],n,a):e[t]=n,c(i)&&!c(e)&&l(e,u(i)),c(e)&&(n=parseInt(t,10),String(n)===t&&0<=n&&n>u(e)&&p(e,n)),e},e);if(c(i)){for(var t=Object.keys(i),n=a&&a.plainObjects?{__proto__:null,0:o}:{0:o},s=0;sa.arrayLimit?l(f(e,a),e.length-1):e}}},{"./formats":41,"side-channel":49}],46:[function(e,t,n){"use strict";function i(e,t,n){for(var r,o=e;null!=(r=o.next);o=r)if(r.key===t)return o.next=r.next,n||(r.next=e.next,e.next=r),r}var r=e("object-inspect"),a=e("es-errors/type");t.exports=function(){var o,t={assert:function(e){if(!t.has(e))throw new a("Side channel does not contain "+r(e))},delete:function(e){var t=o&&o.next,e=function(e,t){if(e)return i(e,t,!0)}(o,e);return e&&t&&t===e&&(o=void 0),!!e},get:function(e){var t=o;if(t)return(t=i(t,e))&&t.value},has:function(e){return e=e,!!(t=o)&&!!i(t,e);var t},set:function(e,t){var n,r;t=t,(r=i(n=o=o||{next:void 0},e=e))?r.value=t:n.next={key:e,next:n.next,value:t}}};return t}},{"es-errors/type":15,"object-inspect":39}],47:[function(e,t,n){"use strict";var r=e("get-intrinsic"),o=e("call-bound"),i=e("object-inspect"),a=e("es-errors/type"),s=r("%Map%",!0),l=o("Map.prototype.get",!0),c=o("Map.prototype.set",!0),u=o("Map.prototype.has",!0),p=o("Map.prototype.delete",!0),f=o("Map.prototype.size",!0);t.exports=!!s&&function(){var n,t={assert:function(e){if(!t.has(e))throw new a("Side channel does not contain "+i(e))},delete:function(e){return!!n&&(e=p(n,e),0===f(n)&&(n=void 0),e)},get:function(e){if(n)return l(n,e)},has:function(e){return!!n&&u(n,e)},set:function(e,t){n=n||new s,c(n,e,t)}};return t}},{"call-bound":7,"es-errors/type":15,"get-intrinsic":20,"object-inspect":39}],48:[function(e,t,n){"use strict";var r=e("get-intrinsic"),o=e("call-bound"),i=e("object-inspect"),a=e("side-channel-map"),s=e("es-errors/type"),l=r("%WeakMap%",!0),c=o("WeakMap.prototype.get",!0),u=o("WeakMap.prototype.set",!0),p=o("WeakMap.prototype.has",!0),f=o("WeakMap.prototype.delete",!0);t.exports=l?function(){var n,r,t={assert:function(e){if(!t.has(e))throw new s("Side channel does not contain "+i(e))},delete:function(e){if(l&&e&&("object"==typeof e||"function"==typeof e)){if(n)return f(n,e)}else if(a&&r)return r.delete(e);return!1},get:function(e){return l&&e&&("object"==typeof e||"function"==typeof e)&&n?c(n,e):r&&r.get(e)},has:function(e){return l&&e&&("object"==typeof e||"function"==typeof e)&&n?p(n,e):!!r&&r.has(e)},set:function(e,t){l&&e&&("object"==typeof e||"function"==typeof e)?(n=n||new l,u(n,e,t)):a&&(r=r||a()).set(e,t)}};return t}:a},{"call-bound":7,"es-errors/type":15,"get-intrinsic":20,"object-inspect":39,"side-channel-map":47}],49:[function(e,t,n){"use strict";var r=e("es-errors/type"),o=e("object-inspect"),i=e("side-channel-list"),a=e("side-channel-map"),s=e("side-channel-weakmap")||a||i;t.exports=function(){var n,t={assert:function(e){if(!t.has(e))throw new r("Side channel does not contain "+o(e))},delete:function(e){return!!n&&n.delete(e)},get:function(e){return n&&n.get(e)},has:function(e){return!!n&&n.has(e)},set:function(e,t){(n=n||s()).set(e,t)}};return t}},{"es-errors/type":15,"object-inspect":39,"side-channel-list":46,"side-channel-map":47,"side-channel-weakmap":48}],50:[function(e,t,n){"use strict";var A=e("punycode/");function w(){this.protocol=null,this.slashes=null,this.auth=null,this.host=null,this.port=null,this.hostname=null,this.hash=null,this.search=null,this.query=null,this.pathname=null,this.path=null,this.href=null}var j=/^([a-z0-9.+-]+:)/i,r=/:[0-9]*$/,E=/^(\/\/?(?!\/)[^?\s]*)(\?[^\s]*)?$/,o=["{","}","|","\\","^","`"].concat(["<",">",'"',"`"," ","\r","\n","\t"]),k=["'"].concat(o),T=["%","/","?",";","#"].concat(k),C=["/","?","#"],O=/^[+a-z0-9A-Z_-]{0,63}$/,D=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,N={javascript:!0,"javascript:":!0},P={javascript:!0,"javascript:":!0},L={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},q=e("qs");function i(e,t,n){var r;return e&&"object"==typeof e&&e instanceof w?e:((r=new w).parse(e,t,n),r)}w.prototype.parse=function(e,t,n){if("string"!=typeof e)throw new TypeError("Parameter 'url' must be a string, not "+typeof e);var r=e.indexOf("?"),r=-1!==r&&r]*)>/i,function(e,t,n,r){return"<"+t+"div"+(t?"":' data-element="'+n+'"')+r+">"}).replace(/<(\/?)(head)([^>]*)>/i,function(e,t,n,r){return"<"+t+"div"+(t?"":' data-element="'+n+'"')+r+">"}).replace(/<(\/?)(body)([^>]*)>/i,function(e,t,n,r){return"<"+t+"div"+(t?"":' data-element="'+n+'"')+r+">"}),u(e)),i=o.find(".book");if(0===i.length)return r=new Error("Invalid gitbook page, redirecting..."),a.reject(r);s&&history.pushState({path:n},null,n),r=(o=u(e)).find("[data-element=head]"),i=o.find(".book"),document.title=r.find("title").text();n=u("head"),n.find("link[rel=prev]").remove(),n.find("link[rel=next]").remove(),n.append(r.find("link[rel=prev]")),n.append(r.find("link[rel=next]")),e=u(".book").attr("class"),o=u(".book-summary").scrollTop();i.toggleClass("with-summary",u(".book").hasClass("with-summary")),u(".book").replaceWith(i),u(".book").attr("class",e),u(".book-summary").scrollTop(o),p.state.$book=u(".book"),w(!c),c&&d(c),a.resolve()}})}).promise();return a.show(n.fail(function(e){console.log(e)}))}location.href=e}function x(){var e=parseInt(u(".body-inner").css("width"),10),t=parseInt(u(".page-wrapper").css("width"),10),e=(u(".navigation-next").css("margin-right",e-t+"px"),l());e.unbind("scroll"),e.scroll(m)}function w(e){var t=u(".book-body").find(".body-inner").find(".page-wrapper"),t=(x(),t&&t[0]&&t[0].focus({preventScroll:!0}),l());e&&t.scrollTop(0),1<(i=u(".book-summary .summary .chapter").filter(function(){var e=u(this).children("a"),t=null;return!!e.length&&(!!(t=(e=e.attr("href"))?e.split("#")[0]:null)&&(e=o.resolve(window.location.pathname,t),window.location.pathname==e))})).length?t.scroll(m):r=i.first()}function S(e){var t,n=u(this),r=n.attr("target");(t=e).metaKey||t.altKey||t.ctrlKey||t.shiftKey||0!==e.button||r||(e.stopPropagation(),e.preventDefault(),(t=n.attr("href"))&&b(t,!0))}t.exports={init:function(){u.ajaxSetup({cache:!1}),history.replaceState({path:window.location.href},""),window.onpopstate=function(e){if(null!==e.state)return b(e.state.path,!1)},u(document).on("click",".navigation-prev",S),u(document).on("click",".navigation-next",S),u(document).on("click",".summary [data-path] a",S),u(document).on("click",".page-inner a",S),u(window).resize(x),w(!1)},goNext:function(){var e=u(".navigation-next").attr("href");e&&b(e,!0)},goPrev:function(){var e=u(".navigation-prev").attr("href");e&&b(e,!0)}}},{"./loading":54,"./platform":56,jquery:29,url:50}],56:[function(e,t,n){var r=e("jquery");t.exports={isMobile:function(){return r(document).width()<=600},isSmallScreen:function(){return r(document).width()<=1240}}},{jquery:29}],57:[function(e,t,n){var r=e("jquery"),o=e("./platform"),i=window.gitbook;function a(e,t){null!=i.state&&s()==e||(i.state.$book.toggleClass("without-animation",!(t=null==t?!0:t)),i.state.$book.toggleClass("with-summary",e),i.storage.set("sidebar",s()))}function s(){return i.state.$book.hasClass("with-summary")}t.exports={init:function(){r(document).on("click",".book-summary li.chapter a",function(e){o.isMobile()&&a(!1,!1)})},isOpen:s,toggle:a,filter:function(t){r(".book-summary").find("li").each(function(){var e=r(this).data("path"),e=null==t||-1!==t.indexOf(e);r(this).toggle(e),e&&r(this).parents("li").show()})}}},{"./platform":56,jquery:29}],58:[function(e,t,n){var l=e("jquery"),e=window.gitbook,r=[],o=0;function c(e){e.preventDefault()}function i(e){var t,o,n,r=l(".book-header"),i=r.find("h1"),a="pull-"+e.position,s=l("",{class:"btn",text:e.text?" "+e.text:"","aria-label":e.label,href:"#"});s.click(e.onClick),e.icon&&l("",{class:e.icon}).prependTo(s),(t=e.dropdown?(n=l("
                                    ",{class:"dropdown "+a+" "+e.className}),s.addClass("toggle-dropdown"),n.append(s),t=e.dropdown,o=l("
                                    ",{class:"dropdown-menu",html:''}),"string"==typeof t?o.append(t):t.map(function(e){return l.isArray(e)?e:[e]}).forEach(function(e){var n=l("
                                    ",{class:"buttons"}),r="size-"+e.length;e.forEach(function(e){e=l.extend({text:"",className:"",onClick:c},e||{});var t=l("