জিরার জন্য স্ট্রাকচার প্লাগইনটি দৈনন্দিন কাজ এবং তাদের বিশ্লেষণের জন্য খুবই উপযোগী; এটি জিরা টিকিটের ভিজ্যুয়ালাইজেশন এবং গঠনকে একটি নতুন স্তরে নিয়ে যায় এবং এটি সব ঠিক বাক্সের বাইরে করে।
এবং, সবাই এটা জানে না, কিন্তু গঠন সূত্রের কার্যকারিতা কেবল আপনার মনকে উড়িয়ে দিতে পারে। সূত্রগুলি ব্যবহার করে, আপনি অত্যন্ত দরকারী টেবিল তৈরি করতে পারেন যা কাজগুলির সাথে কাজকে ব্যাপকভাবে সহজ করতে পারে এবং সবচেয়ে গুরুত্বপূর্ণভাবে, তারা রিলিজ, মহাকাব্য এবং প্রকল্পগুলির গভীর বিশ্লেষণ করতে কার্যকর।
এই নিবন্ধে, আপনি দেখতে পাবেন কিভাবে আপনার নিজস্ব সূত্র তৈরি করতে হয়, সহজ উদাহরণ থেকে শুরু করে এবং জটিল, কিন্তু বরং দরকারী, ক্ষেত্রে শেষ হয়।
তাহলে, এই লেখাটি কার জন্য? কেউ ভাবতে পারে, কেন একটি নিবন্ধ লিখবেন যখন ALM ওয়ার্কস ওয়েবসাইটে অফিসিয়াল ডকুমেন্টেশন পাঠকদের জন্য খনন করার জন্য অপেক্ষা করছে। এটি সত্য। যাইহোক, আমি সেই ব্যক্তিদের মধ্যে একজন যাদের সামান্যতম ধারণাও ছিল না যে কাঠামো এত ব্যাপক কার্যকারিতা লুকিয়ে রেখেছে: "অপেক্ষা করুন, এটি সর্বদা একটি বিকল্প ছিল?!" এই উপলব্ধিটি আমাকে ভাবতে বাধ্য করেছে, এমন আরও কিছু লোক থাকতে পারে যারা এখনও জানেন না যে তারা সূত্র এবং কাঠামোর সাথে কী ধরনের কাজ করতে পারে।
এই নিবন্ধটি তাদের জন্যও কার্যকর হবে যারা ইতিমধ্যে সূত্রের সাথে পরিচিত। আপনি কাস্টম ক্ষেত্রগুলি ব্যবহার করার জন্য কিছু আকর্ষণীয় ব্যবহারিক বিকল্প শিখবেন এবং, সম্ভবত, আপনার প্রকল্পগুলির জন্য সেগুলির কিছু ধার নেবেন৷ যাইহোক, যদি আপনার নিজের কোনও আকর্ষণীয় উদাহরণ থাকে, আপনি যদি মন্তব্যে সেগুলি শেয়ার করেন তবে আমি খুশি হব .
প্রতিটি উদাহরণ বিশদভাবে বিশ্লেষণ করা হয়েছে, সমস্যার বর্ণনা থেকে কোডের ব্যাখ্যা পর্যন্ত, যথেষ্ট পরিমাণে যাতে কোনো প্রশ্ন অবশিষ্ট না থাকে। অবশ্যই, ব্যাখ্যাগুলির পাশাপাশি, প্রতিটি উদাহরণ কোড দ্বারা চিত্রিত করা হয়েছে যা আপনি বিশ্লেষণে না গিয়ে নিজের জন্য চেষ্টা করতে পারেন।
আপনার যদি পড়তে ভালো না লাগে, কিন্তু আপনি সূত্রে আগ্রহী হন, তাহলে ALM Works ওয়েবিনারগুলি দেখুন। এই 40 মিনিটের মধ্যে মৌলিক ব্যাখ্যা; তথ্য সেখানে একটি খুব সংকুচিত পদ্ধতিতে উপস্থাপন করা হয়.
উদাহরণগুলি বোঝার জন্য আপনার কোন অতিরিক্ত জ্ঞানের প্রয়োজন নেই, তাই যে কেউ জিরা এবং কাঠামোর সাথে কাজ করেছেন তারা কোনও সমস্যা ছাড়াই তাদের টেবিলে উদাহরণগুলি পুনরাবৃত্তি করতে সক্ষম হবেন।
ডেভেলপাররা তাদের Expr ভাষার সাথে মোটামুটি নমনীয় সিনট্যাক্স প্রদান করেছে। মূলত, এখানে দর্শনটি হল "আপনার ইচ্ছামত লিখুন এবং এটি কাজ করবে"।
চল শুরু করা যাক!
সুতরাং, কেন আমরা সব সূত্র ব্যবহার করতে চাই? ঠিক আছে, কখনও কখনও দেখা যাচ্ছে যে আমাদের কাছে পর্যাপ্ত স্ট্যান্ডার্ড জিরা ক্ষেত্র নেই, যেমন “অ্যাসাইনি”, “স্টোরি পয়েন্টস” ইত্যাদি। অথবা আমাদের নির্দিষ্ট ক্ষেত্রগুলির জন্য কিছু পরিমাণ গণনা করতে হবে, সংস্করণ অনুসারে অবশিষ্ট ক্ষমতা প্রদর্শন করতে হবে এবং কতবার টাস্কটি তার স্থিতি পরিবর্তন করেছে তা খুঁজে বের করতে হবে। হয়তো আমরা আমাদের কাঠামোকে সহজে পড়ার জন্য বেশ কয়েকটি ক্ষেত্রকে একটিতে একত্রিত করতে চাই।
এই সমস্যাগুলি সমাধান করার জন্য, আমাদের সূত্রের প্রয়োজন, এবং আমরা কাস্টম ক্ষেত্র তৈরি করতে সেগুলি ব্যবহার করব।
একটি সূত্র কিভাবে কাজ করে তা বোঝার জন্য প্রথমে আমাদের যা করতে হবে। এটি আমাদের একটি স্ট্রিং এ কিছু ধরনের অপারেশন প্রয়োগ করার অনুমতি দেয়। যেহেতু আমরা কাঠামোর মধ্যে অনেক কাজ আপলোড করছি, সূত্রটি পুরো টেবিলের প্রতিটি লাইনে প্রয়োগ করা হয়। সাধারণত, এর সমস্ত ক্রিয়াকলাপগুলি এই লাইনগুলিতে কাজগুলির সাথে কাজ করার লক্ষ্যে থাকে।
সুতরাং, যদি আমরা সূত্রটিকে কিছু জিরা ক্ষেত্র প্রদর্শন করতে বলি, উদাহরণস্বরূপ, “অ্যাসাইনি”, তাহলে প্রতিটি কাজের জন্য সূত্রটি প্রয়োগ করা হবে এবং আমাদের কাছে আরেকটি “অ্যাসাইনি” কলাম থাকবে।
সূত্রগুলি কয়েকটি মৌলিক সত্তা নিয়ে গঠিত:
আমরা কিছু উদাহরণের মাধ্যমে সূত্র এবং তাদের সিনট্যাক্সের সাথে আরও পরিচিত হব, এবং আমরা ছয়টি ব্যবহারিক ক্ষেত্রের মধ্য দিয়ে যেতে যাচ্ছি।
প্রতিটি উদাহরণ দেখার আগে, আমরা কোন কাঠামো বৈশিষ্ট্যগুলি ব্যবহার করছি তা নির্দেশ করব; নতুন বৈশিষ্ট্য যা এখনও ব্যাখ্যা করা হয়নি বোল্ডে হবে। নিম্নলিখিত প্রতিটি উদাহরণে জটিলতার ক্রমবর্ধমান স্তর থাকবে। আপনাকে ধীরে ধীরে গুরুত্বপূর্ণ সূত্র বৈশিষ্ট্যগুলির সাথে পরিচয় করিয়ে দেওয়ার জন্য সেগুলি সাজানো হয়েছে।
এখানে মৌলিক কাঠামো যা আপনি প্রতিবার দেখতে পাবেন:
এই উদাহরণগুলি পরিবর্তনশীল ম্যাপিং থেকে জটিল অ্যারে পর্যন্ত বিষয়গুলি কভার করে:
প্রথমে, আসুন জেনে নেওয়া যাক কিভাবে সূত্র দিয়ে কাস্টম ক্ষেত্র তৈরি করা যায়। স্ট্রাকচারের উপরের ডানদিকে, সমস্ত কলামের শেষে, একটি "+" আইকন রয়েছে — এটিতে ক্লিক করুন। প্রদর্শিত ক্ষেত্রটিতে, "সূত্র …" লিখুন এবং উপযুক্ত আইটেমটি নির্বাচন করুন।
চলুন একটি সূত্র সংরক্ষণ আলোচনা করা যাক. দুর্ভাগ্যবশত, কোথাও আলাদাভাবে একটি নির্দিষ্ট সূত্র সংরক্ষণ করা এখনও সম্ভব নয় (কেবল আপনার নোটবুকে, যেমন আমি করি)। ALM ওয়ার্কস ওয়েবিনারে, দলটি উল্লেখ করেছে যে তারা সূত্রের ব্যাঙ্কে কাজ করছে, কিন্তু আপাতত তাদের সংরক্ষণ করার একমাত্র উপায় হল সূত্রের সাথে পুরো দৃশ্যটি সংরক্ষণ করা।
যখন আমরা একটি সূত্রের উপর কাজ শেষ করি, তখন আমাদের কাঠামোর ভিউতে ক্লিক করতে হবে (এটি সম্ভবত একটি নীল তারকাচিহ্ন দিয়ে চিহ্নিত করা হবে) এবং বর্তমান ভিউটি ওভাররাইট করতে "সংরক্ষণ করুন" এ ক্লিক করতে হবে। অথবা আপনি একটি নতুন ভিউ তৈরি করতে "Save As..." এ ক্লিক করতে পারেন। (অন্যান্য জিরা ব্যবহারকারীদের কাছে এটি উপলব্ধ করতে ভুলবেন না কারণ নতুন ভিউ ডিফল্টরূপে ব্যক্তিগত।)
সূত্রটি একটি নির্দিষ্ট দৃশ্যে অবশিষ্ট ক্ষেত্রগুলিতে সংরক্ষণ করা হবে এবং আপনি এটি "বিশদ বিবরণ দেখুন" মেনুর "উন্নত" ট্যাবে দেখতে পাবেন।
সংস্করণ 8.2 দিয়ে শুরু করে, কাঠামোতে এখন 3টি দ্রুত ক্লিকে সূত্র সংরক্ষণ করার ক্ষমতা রয়েছে।
সংরক্ষণ ডায়ালগ সূত্র সম্পাদনা উইন্ডো থেকে উপলব্ধ. যদি এই উইন্ডোটি খোলা না থাকে, তবে শুধুমাত্র পছন্দসই কলামের ত্রিভুজ ▼ আইকনে ক্লিক করুন।
সম্পাদনা উইন্ডোতে আমরা "সংরক্ষিত কলাম" ক্ষেত্রটি দেখতে পাই, ডানদিকে একটি নীল বিজ্ঞপ্তি সহ একটি আইকন রয়েছে, যার অর্থ সূত্রের পরিবর্তনগুলি সংরক্ষণ করা হয়নি৷ এই আইকনে ক্লিক করুন এবং "সংরক্ষণ হিসাবে..." বিকল্পটি নির্বাচন করুন।
তারপর আমাদের কলামের জন্য নাম লিখুন (সূত্র) এবং কোন স্থানটি সংরক্ষণ করতে হবে তা চয়ন করুন। "আমার কলাম" যদি আমরা এটি একটি ব্যক্তিগত তালিকায় সংরক্ষণ করতে চাই। "গ্লোবাল", যাতে সূত্রটি সাধারণ তালিকায় সংরক্ষিত হবে, যেখানে এটি আপনার কাঠামোর সমস্ত ব্যবহারকারী দ্বারা সম্পাদনা করা যেতে পারে৷ "সংরক্ষণ করুন" এ ক্লিক করুন।
এখন আমাদের সূত্র সংরক্ষিত. আমরা যেকোন স্ট্রাকচারে এটি লোড করতে পারি বা যে কোন জায়গা থেকে রিসেভ করতে পারি। সূত্রটি পুনরুদ্ধার করার মাধ্যমে, এটি ব্যবহার করা হয়েছে এমন সমস্ত কাঠামোতে এটি আপডেট করা হবে।
ভেরিয়েবল ম্যাপিংও সূত্রের সাথে সংরক্ষণ করা হয়, তবে আমরা ম্যাপিং সম্পর্কে পরে কথা বলব।
এখন, আমাদের উদাহরণের দিকে এগিয়ে যাওয়া যাক!
আমাদের কাজের তালিকা সহ একটি টেবিল প্রয়োজন, সেইসাথে সেই কাজগুলিতে কাজ করার জন্য শুরু এবং শেষের তারিখ। এটিকে একটি পৃথক এক্সেল-গ্যান্টে রপ্তানি করার জন্য আমাদের টেবিলটিও প্রয়োজন। দুর্ভাগ্যবশত, জিরা এবং কাঠামো বাক্সের বাইরে এই ধরনের তারিখগুলি কীভাবে প্রদান করতে হয় তা জানে না।
শুরু এবং শেষের তারিখগুলি হল নির্দিষ্ট স্থিতিতে স্থানান্তরের তারিখ, আমাদের ক্ষেত্রে এগুলি হল "প্রগতিতে" এবং "বন্ধ"৷ আমাদের এই তারিখগুলি নিতে হবে, এবং তাদের প্রতিটিকে একটি পৃথক ক্ষেত্রে প্রদর্শন করতে হবে (এটি গ্যান্টে আরও রপ্তানির জন্য প্রয়োজনীয়)। সুতরাং, আমাদের দুটি ক্ষেত্র (দুটি সূত্র) থাকবে।
ব্যবহৃত কাঠামো বৈশিষ্ট্য
একটি কোড উদাহরণ
শুরুর তারিখের জন্য ক্ষেত্র:
firstTransitionToStart
শেষ তারিখের জন্য ক্ষেত্র:
latestTransitionToDone
এই ক্ষেত্রে, কোডটি একটি একক পরিবর্তনশীল, প্রথম ট্রানজিশন টু স্টার্ট, শুরুর তারিখ ক্ষেত্রের জন্য, এবং দ্বিতীয় ক্ষেত্রের জন্য সর্বশেষ ট্রানজিশনটোডন।
আপাতত শুরুর তারিখ ক্ষেত্রের উপর ফোকাস করা যাক। আমাদের লক্ষ্য হল টাস্কটি "প্রগতিতে" স্থিতিতে স্থানান্তরিত হওয়ার তারিখটি পাওয়া (এটি টাস্কের যৌক্তিক শুরুর সাথে মিলে যায়), তাই পরিবর্তনশীলটির নামকরণ করা হয়েছে, পরে অনুমান করার প্রয়োজনীয়তা রোধ করার জন্য, "প্রথম রূপান্তর" হিসাবে শুরু"।
একটি তারিখ একটি পরিবর্তনশীল করতে, আমরা পরিবর্তনশীল ম্যাপিং চালু. আসুন "সংরক্ষণ করুন" বোতামে ক্লিক করে আমাদের সূত্র সংরক্ষণ করি।
আমাদের ভেরিয়েবল "ভেরিয়েবল" বিভাগে উপস্থিত হয়েছে, এর পাশে একটি বিস্ময়বোধক চিহ্ন রয়েছে। কাঠামো নির্দেশ করে যে এটি জিরার একটি ক্ষেত্রের সাথে একটি ভেরিয়েবল লিঙ্ক করতে পারে না এবং আমাদের এটি নিজেদের করতে হবে (অর্থাৎ এটি মানচিত্র)।
ভেরিয়েবলে ক্লিক করুন এবং ম্যাপিং ইন্টারফেসে যান। ক্ষেত্র বা প্রয়োজনীয় অপারেশন নির্বাচন করুন — অপারেশন "ট্রানজিশন ডেট …" দেখুন। এটি করতে, নির্বাচন ক্ষেত্রে "ট্রানজিশন" লিখুন। আপনাকে একবারে বেশ কয়েকটি বিকল্প অফার করা হবে, এবং তাদের মধ্যে একটি আমাদের জন্য উপযুক্ত: "প্রগতিতে প্রথম পরিবর্তন"। কিন্তু ম্যাপিং কীভাবে কাজ করে তা প্রদর্শন করার জন্য, আসুন "ট্রানজিশন তারিখ …" বিকল্পটি বেছে নেওয়া যাক।
এর পরে, আপনাকে সেই স্থিতি চয়ন করতে হবে যেখানে রূপান্তরটি ঘটেছে এবং এই রূপান্তরের ক্রম - প্রথম বা শেষ।
"স্থিতি" - "স্থিতি: অগ্রগতিতে" (বা আপনার ওয়ার্কফ্লোতে সংশ্লিষ্ট স্থিতি) নির্বাচন করুন বা প্রবেশ করুন, এবং "পরিবর্তন" - "স্থিতিতে প্রথম রূপান্তর", যেহেতু একটি টাস্কে কাজ শুরু করাই প্রথম রূপান্তর। সংশ্লিষ্ট স্থিতিতে।
যদি "ট্রানজিশন ডেট..." এর পরিবর্তে আমরা প্রাথমিকভাবে প্রস্তাবিত বিকল্প "প্রগতিতে প্রথম স্থানান্তর" বেছে নিই, তাহলে ফলাফল প্রায় একই হবে — কাঠামো আমাদের জন্য প্রয়োজনীয় প্যারামিটার বেছে নেবে। একমাত্র জিনিস হল, "স্থিতি: অগ্রগতি" এর পরিবর্তে, আমাদের "বিভাগ: অগ্রগতিতে" থাকবে।
আমাকে একটি গুরুত্বপূর্ণ বৈশিষ্ট্য নোট করতে দিন: একটি স্থিতি এবং একটি বিভাগ দুটি ভিন্ন জিনিস। একটি স্ট্যাটাস একটি নির্দিষ্ট স্ট্যাটাস, এটি দ্ব্যর্থহীন, কিন্তু একটি ক্যাটাগরিতে বেশ কয়েকটি স্ট্যাটাস থাকতে পারে। শুধুমাত্র তিনটি বিভাগ আছে: "করতে হবে", "প্রগতিতে আছে" এবং "সম্পন্ন"। জিরাতে, তারা সাধারণত ধূসর, নীল এবং সবুজ রং দিয়ে চিহ্নিত করা হয়। স্ট্যাটাস অবশ্যই এই শ্রেণীগুলির মধ্যে একটির অন্তর্গত।
একই বিভাগের স্ট্যাটাস নিয়ে বিভ্রান্তি এড়াতে আমি এই ধরনের ক্ষেত্রে একটি নির্দিষ্ট স্ট্যাটাস নির্দেশ করার পরামর্শ দিই। উদাহরণস্বরূপ, আমাদের প্রকল্পে "টু ডু" বিভাগের দুটি স্ট্যাটাস আছে, "ওপেন" এবং "কিউএ কিউ"।
আসুন আমাদের উদাহরণে ফিরে যাই।
একবার আমরা প্রয়োজনীয় বিকল্পগুলি নির্বাচন করার পরে, আমরা firstTransitionToStart ভেরিয়েবলের ম্যাপিং বিকল্পগুলি সম্পূর্ণ করতে "< ভেরিয়েবল তালিকায় ফিরে যান" এ ক্লিক করতে পারি। আমরা যদি সবকিছু ঠিকঠাক করি তবে আমরা একটি সবুজ চেক চিহ্ন দেখতে পাব।
একই সময়ে, আমাদের কাস্টম ফিল্ডে, আমরা কিছু অদ্ভুত সংখ্যা দেখতে পাই যেগুলি একেবারেই তারিখের মতো দেখায় না। আমাদের ক্ষেত্রে, সূত্রের ফলাফল হবে firstTransitionToStart ভেরিয়েবলের মান, এবং এর মান জানুয়ারি 1970 থেকে মিলিসেকেন্ড। সঠিক তারিখ পেতে, আমাদের একটি নির্দিষ্ট সূত্র প্রদর্শন বিন্যাস নির্বাচন করতে হবে।
বিন্যাস নির্বাচন সম্পাদনা উইন্ডোর একেবারে নীচে অবস্থিত। "সাধারণ" সেখানে ডিফল্টরূপে নির্বাচিত হয়। তারিখ সঠিকভাবে প্রদর্শন করার জন্য আমাদের "তারিখ / সময়" প্রয়োজন।
দ্বিতীয় ক্ষেত্রের জন্য, সর্বশেষ ট্রানজিশনটুডন, আমরা একই কাজ করব। শুধুমাত্র পার্থক্য হল ম্যাপিং করার সময় আমরা ইতিমধ্যেই "সম্পন্ন" বিভাগ নির্বাচন করতে পারি, এবং স্থিতি নয় (যেহেতু সাধারণত শুধুমাত্র একটি দ্ব্যর্থহীন কাজ সমাপ্তির স্থিতি থাকে)। আমরা ট্রানজিশন প্যারামিটার হিসাবে "সর্বশেষ ট্রানজিশন" নির্বাচন করি, যেহেতু আমরা "সম্পন্ন" বিভাগে সবচেয়ে সাম্প্রতিক পরিবর্তনে আগ্রহী।
দুটি ক্ষেত্রের জন্য চূড়ান্ত ফলাফল এই মত দেখাবে.
এখন দেখা যাক কিভাবে একই ফলাফল অর্জন করা যায়, কিন্তু আমাদের নিজস্ব ডিসপ্লে ফরম্যাট দিয়ে।
আমরা পূর্ববর্তী উদাহরণ থেকে তারিখ প্রদর্শন বিন্যাসে সন্তুষ্ট নই, যেহেতু আমাদের গ্যান্ট টেবিলের জন্য একটি বিশেষ প্রয়োজন — “01.01.2022”।
স্ট্রাকচারে বিল্ট ফাংশন ব্যবহার করে তারিখগুলি প্রদর্শন করা যাক, আমাদের উপযুক্ত বিন্যাসটি নির্দিষ্ট করে।
স্ট্রাকচার ফিচার ব্যবহার করা হয়েছে
একটি কোড উদাহরণ
FORMAT_DATETIME(firstTransitionToStart;"dd.MM.yyyy")
ডেভেলপাররা আমাদের নিজস্ব বিন্যাসে তারিখটি প্রদর্শনের জন্য আলাদা একটি সহ অনেকগুলি বিভিন্ন ফাংশন প্রদান করেছে: FORMAT_DATETIME; যে আমরা ব্যবহার করতে যাচ্ছেন কি. ফাংশন দুটি আর্গুমেন্ট ব্যবহার করে: একটি তারিখ এবং পছন্দসই বিন্যাসের একটি স্ট্রিং।
আমরা আগের উদাহরণের মতো একই ম্যাপিং নিয়ম ব্যবহার করে firstTransitionToStart ভেরিয়েবল (প্রথম আর্গুমেন্ট) সেট আপ করেছি। দ্বিতীয় আর্গুমেন্ট হল একটি স্ট্রিং যা বিন্যাসটি নির্দিষ্ট করে এবং আমরা এটিকে এভাবে সংজ্ঞায়িত করি: “dd.MM.yyyy”। এটি আমরা যে ফর্মটি চাই তার সাথে মিলে যায়, "01.01.2022"৷
সুতরাং, আমাদের সূত্র অবিলম্বে পছন্দসই আকারে একটি ফলাফল দেবে। সুতরাং, আমরা ফিল্ড সেটিংসে "সাধারণ" বিকল্পটি রাখতে পারি।
কাজের শেষ তারিখ সহ দ্বিতীয় ক্ষেত্রটি একইভাবে করা হয়। ফলস্বরূপ, কাঠামোটি নীচের চিত্রের মতো হওয়া উচিত।
নীতিগতভাবে, সূত্র সিনট্যাক্সের সাথে কাজ করার কোন উল্লেখযোগ্য অসুবিধা নেই। আপনি একটি পরিবর্তনশীল প্রয়োজন হলে, তার নাম লিখুন; আপনার যদি একটি ফাংশনের প্রয়োজন হয়, আবার, শুধু তার নাম লিখুন এবং আর্গুমেন্টগুলি পাস করুন (যদি প্রয়োজন হয়)।
যখন স্ট্রাকচার একটি অজানা নামের মুখোমুখি হয়, তখন এটি একটি পরিবর্তনশীল বলে ধরে নেয় এবং এটি নিজেই ম্যাপ করার চেষ্টা করে, বা আমাদের সাহায্যের জন্য জিজ্ঞাসা করে।
যাইহোক, একটি গুরুত্বপূর্ণ নোট: কাঠামোটি কেস-সংবেদনশীল, তাই firstTransitionToStart, firsttransitiontostart এবং firSttrAnsItiontOStarT একই পরিবর্তনশীল। একই নিয়ম ফাংশন প্রযোজ্য. দ্ব্যর্থহীন কোড শৈলী অর্জনের জন্য, উদাহরণগুলিতে আমরা MSDN দ্বারা ক্যাপিটালাইজেশন কনভেনশনের নিয়মগুলি মেনে চলার চেষ্টা করব।
এখন চলুন সিনট্যাক্সের দিকে তাকাই এবং ফলাফল প্রদর্শনের জন্য একটি বিশেষ বিন্যাস দেখি।
আমরা নিয়মিত কাজগুলির সাথে কাজ করি (টাস্ক, বাগ, ইত্যাদি) এবং স্টোরি-টাইপ টাস্কগুলির সাথে যেগুলিতে সাবটাস্ক রয়েছে৷ কিছু সময়ে, একটি নির্দিষ্ট সময়ের মধ্যে কর্মচারী কোন কাজ এবং সাবটাস্কগুলিতে কাজ করেছে তা আমাদের খুঁজে বের করতে হবে।
সমস্যা হল যে অনেক সাবটাস্ক গল্প সম্পর্কে তথ্য প্রদান করে না, কারণ সেগুলিকে "গল্পে কাজ করা", "সেটিং আপ" বা, উদাহরণস্বরূপ, "প্রভাব সক্রিয় করা" বলা হয়। এবং যদি আমরা একটি নির্দিষ্ট সময়ের জন্য কাজের তালিকার জন্য অনুরোধ করি, আমরা অন্য কোনও দরকারী তথ্য ছাড়াই "গল্পে কাজ করা" নামের এক ডজন কাজ পাব।
আমরা দুটি কলামে বিভক্ত একটি তালিকার সাথে একটি দৃশ্য দেখতে চাই: একটি কার্য এবং একটি মূল কাজ, যাতে ভবিষ্যতে কর্মীদের দ্বারা এই ধরনের একটি তালিকাকে গোষ্ঠীভুক্ত করা সম্ভব হয়৷
আমাদের প্রকল্পে, আমাদের কাছে দুটি বিকল্প আছে যখন একটি টাস্কের একজন অভিভাবক থাকতে পারে:
সুতরাং, আমাদের অবশ্যই:
তথ্যের উপলব্ধি সহজ করার জন্য, আমরা টাস্ক টাইপের পাঠ্যকে রঙিন করব: অর্থাৎ, হয় "[গল্প]" বা "[মহাকাব্য]"।
আমরা যা ব্যবহার করব:
একটি কোড উদাহরণ
if( Parent.Issuetype = "Story"; """{color:green}[${Parent.Issuetype}]{color} ${Parent.Summary}"""; EpicLink; """{color:#713A82}[${EpicLink.Issuetype}]{color} ${EpicLink.EpicName}""" )
কেন সূত্র একটি if শর্ত দিয়ে শুরু হয়, যদি আমাদের শুধুমাত্র একটি স্ট্রিং আউটপুট করতে হয় এবং সেখানে টাস্ক টাইপ এবং নাম সন্নিবেশ করতে হয়? টাস্ক ফিল্ড অ্যাক্সেস করার কিছু সার্বজনীন উপায় নেই? হ্যাঁ, তবে কাজ এবং মহাকাব্যের জন্য, এই ক্ষেত্রগুলির নাম আলাদাভাবে দেওয়া হয়েছে এবং আপনাকে সেগুলিকে আলাদাভাবে অ্যাক্সেস করতে হবে, এটি জিরার একটি বৈশিষ্ট্য।
পার্থক্যগুলি অভিভাবক অনুসন্ধানের স্তরে শুরু হয়। একটি সাবটাস্কের জন্য, অভিভাবক "প্যারেন্ট ইস্যু" জিরা ফিল্ডে থাকেন এবং একটি নিয়মিত কাজের জন্য, এপিক হবেন প্যারেন্ট, "এপিক লিঙ্ক" ফিল্ডে অবস্থিত৷ সেই অনুযায়ী, এই ক্ষেত্রগুলি অ্যাক্সেস করার জন্য আমাদের দুটি ভিন্ন বিকল্প লিখতে হবে।
এই যেখানে আমরা একটি যদি শর্ত প্রয়োজন. এক্সপ্র ভাষার শর্ত মোকাবেলার বিভিন্ন উপায় রয়েছে। তাদের মধ্যে পছন্দ স্বাদ একটি বিষয়।
একটি "এক্সেল-মত" পদ্ধতি আছে:
if (condition1; result1; condition2; result2 … )
অথবা আরও একটি "কোড-মত" পদ্ধতি:
if condition1 : result1 else if condition2 : result2 else result3
উদাহরণে, আমি প্রথম বিকল্পটি ব্যবহার করেছি; এখন আসুন একটি সরলীকৃত উপায়ে আমাদের কোডটি দেখি:
if( Parent.Issuetype = "Story"; Some kind of result 1; EpicLink; Some kind of result 2 )
আমরা দুটি সুস্পষ্ট শর্ত দেখতে পাই:
আসুন তারা কী করে তা খুঁজে বের করা যাক, এবং প্রথমটি, Parent.Issuetype="Story" দিয়ে শুরু করি৷
এই ক্ষেত্রে, অভিভাবক হল একটি পরিবর্তনশীল যা স্বয়ংক্রিয়ভাবে "অভিভাবক সমস্যা" ক্ষেত্রের সাথে ম্যাপ করা হয়। এখানেই, যেমনটি আমরা উপরে আলোচনা করেছি, সাবটাস্কের জন্য অভিভাবক থাকা উচিত। ডট নোটেশন (.) ব্যবহার করে, আমরা এই অভিভাবকের সম্পত্তি অ্যাক্সেস করি, বিশেষ করে, ইস্যুটাইপ সম্পত্তি, যা "ইস্যু টাইপ" জিরা ক্ষেত্রের সাথে মিলে যায়। দেখা যাচ্ছে যে পুরো Parent.Issuetype লাইনটি আমাদের অভিভাবক টাস্কের ধরণ প্রদান করে, যদি এই ধরনের একটি টাস্ক থাকে।
উপরন্তু, আমাদের কিছু সংজ্ঞায়িত বা মানচিত্র করতে হবে না, কারণ ডেভেলপাররা ইতিমধ্যেই আমাদের জন্য তাদের যথাসাধ্য চেষ্টা করেছে৷ এখানে, উদাহরণস্বরূপ, ভাষাতে পূর্বনির্ধারিত সমস্ত বৈশিষ্ট্যের (জিরা ক্ষেত্র সহ) একটি লিঙ্ক, এবং এখানে আপনি সমস্ত স্ট্যান্ডার্ড ভেরিয়েবলের একটি তালিকা দেখতে পারেন, যা অতিরিক্ত সেটিংস ছাড়াই নিরাপদে অ্যাক্সেস করা যেতে পারে।
সুতরাং, প্রথম শর্ত হল প্যারেন্ট টাস্কের ধরন Story কিনা তা দেখতে হবে। যদি প্রথম শর্তটি সন্তুষ্ট না হয়, তাহলে প্যারেন্ট টাস্কের ধরন গল্প নয়, বা এটি একেবারেই বিদ্যমান নেই। এবং এটি আমাদের দ্বিতীয় শর্তে নিয়ে আসে: এপিকলিঙ্ক।
প্রকৃতপক্ষে, এটি যখন আমরা পরীক্ষা করি যে "এপিক লিঙ্ক" জিরা ক্ষেত্রটি পূর্ণ হয়েছে কিনা (অর্থাৎ, আমরা এটির অস্তিত্ব পরীক্ষা করি)। EpicLink ভেরিয়েবলটিও স্ট্যান্ডার্ড এবং ম্যাপ করার প্রয়োজন নেই। দেখা যাচ্ছে যে টাস্কটিতে এপিক লিঙ্ক থাকলে আমাদের অবস্থা সন্তুষ্ট।
এবং তৃতীয় বিকল্পটি হল যখন কোনও শর্ত পূরণ করা হয় না, অর্থাৎ, টাস্কটির কোনও অভিভাবক বা এপিক লিঙ্ক নেই। এই ক্ষেত্রে, আমরা কিছু প্রদর্শন করি না এবং ক্ষেত্রটি খালি রাখি না। এটি স্বয়ংক্রিয়ভাবে সম্পন্ন হয় কারণ আমরা কোনো ফলাফল পাব না।
আমরা শর্তগুলি বের করেছি, এখন ফলাফলের দিকে যাওয়া যাক। উভয় ক্ষেত্রেই, এটি পাঠ্য এবং বিশেষ বিন্যাস সহ একটি স্ট্রিং।
ফলাফল 1 (যদি অভিভাবক গল্প হয়):
"""{color:green}[${Parent.Issuetype}]{color} ${Parent.Summary}"""
ফলাফল 2 (যদি এপিক লিঙ্ক থাকে):
"""{color:#713A82}[${EpicLink.Issuetype}]{color} ${EpicLink.EpicName}"""
উভয় ফলাফলই গঠনে একই রকম: উভয়ই আউটপুট স্ট্রিং-এর শুরুতে এবং শেষে ট্রিপল কোট “”” নিয়ে গঠিত, খোলার {color: COLOR} এবং ক্লোজিং {color} ব্লকের কালার স্পেসিফিকেশন, সেইসাথে অপারেশনগুলির মাধ্যমে সম্পন্ন করা হয়েছে $ প্রতীক। ট্রিপল কোটগুলি কাঠামোকে বলে যে ভিতরে ভেরিয়েবল, অপারেশন বা ফর্ম্যাটিং ব্লক (যেমন রঙ) থাকবে।
প্রথম শর্তের ফলাফলের জন্য, আমরা:
এইভাবে, আমরা "[গল্প] কিছু কাজের নাম" স্ট্রিং পাই। আপনি অনুমান করতে পারেন, সারাংশ একটি আদর্শ পরিবর্তনশীল. এই ধরনের স্ট্রিং নির্মাণের স্কিমটি আরও পরিষ্কার করতে, আমাকে অফিসিয়াল ডকুমেন্টেশন থেকে একটি ছবি শেয়ার করতে দিন।
একইভাবে, আমরা দ্বিতীয় ফলাফলের জন্য স্ট্রিং সংগ্রহ করি, কিন্তু হেক্স কোডের মাধ্যমে রঙ সেট করি। আমি বুঝতে পেরেছি যে মহাকাব্যের রঙ ছিল "#713A82" (মন্তব্যে, যাইহোক, আপনি এপিকের জন্য আরও সঠিক রঙের পরামর্শ দিতে পারেন)। এপিকের জন্য পরিবর্তিত ক্ষেত্রগুলি (বৈশিষ্ট্য) সম্পর্কে ভুলবেন না। “সারাংশ”-এর পরিবর্তে, “EpicName” ব্যবহার করুন, “Parent”-এর পরিবর্তে “EpicLink” ব্যবহার করুন।
ফলস্বরূপ, আমাদের সূত্রের স্কিমটি শর্তের সারণী হিসাবে উপস্থাপন করা যেতে পারে।
শর্ত: অভিভাবক-টাস্ক বিদ্যমান, এবং এর ধরন হল গল্প।
ফলাফল: প্যারেন্ট-টাস্ক এবং এর নামের সবুজ ধরন সহ লাইন।
শর্ত: এপিক লিঙ্ক ক্ষেত্রটি পূরণ করা হয়েছে।
ফলাফল: টাইপ এবং এর নামের মহাকাব্য রঙের সাথে রেখা।
ডিফল্টরূপে, ক্ষেত্রের মধ্যে "সাধারণ" প্রদর্শন বিকল্পটি নির্বাচন করা হয়, এবং যদি আপনি এটি পরিবর্তন না করেন, ফলাফলটি রঙ পরিবর্তন এবং ব্লকগুলি সনাক্ত না করেই সরল পাঠ্যের মতো দেখাবে৷ আপনি যদি প্রদর্শন বিন্যাসকে "উইকি মার্কআপ" এ পরিবর্তন করেন, তাহলে পাঠ্যটি রূপান্তরিত হবে।
এখন, আসুন এমন ভেরিয়েবলের সাথে পরিচিত হই যা জিরা ক্ষেত্রগুলির সাথে সম্পর্কিত নয় — স্থানীয় ভেরিয়েবল।
আগের উদাহরণ থেকে, আপনি শিখেছেন যে আমরা গল্পের ধরনের কাজ নিয়ে কাজ করছি, যার সাবটাস্ক আছে। এটি অনুমান সহ একটি বিশেষ ক্ষেত্রে জন্ম দেয়। একটি গল্পের স্কোর পেতে, আমরা এর সাবটাস্কগুলির স্কোরগুলিকে সংক্ষিপ্ত করি, যা বিমূর্ত গল্পের পয়েন্টগুলিতে অনুমান করা হয়।
পদ্ধতিটি অস্বাভাবিক, তবে এটি আমাদের জন্য কাজ করে। সুতরাং, যখন গল্পের একটি অনুমান নেই, কিন্তু সাবটাস্কগুলি করে, কোন সমস্যা নেই, কিন্তু যখন গল্প এবং সাবটাস্ক উভয়েরই একটি অনুমান থাকে, তখন স্ট্রাকচার থেকে স্ট্যান্ডার্ড বিকল্প, “Σ স্টোরি পয়েন্টস”, ভুলভাবে কাজ করে।
এর কারণ হল গল্পের অনুমান সাব-টাস্কের যোগফলের সাথে যোগ করা হয়েছে। ফলস্বরূপ, গল্পে ভুল পরিমাণ প্রদর্শিত হয়। আমরা এটি এড়াতে চাই এবং গল্পে প্রতিষ্ঠিত অনুমান এবং সাবটাস্কের যোগফলের সাথে অসঙ্গতির একটি ইঙ্গিত যোগ করতে চাই।
আমাদের বেশ কয়েকটি শর্তের প্রয়োজন, যেহেতু এটি সমস্ত নির্ভর করে গল্পে অনুমান সেট করা হয়েছে কিনা তার উপর।
তাই শর্তগুলি হল:
যখন গল্পের কোনো অনুমান থাকে না , তখন আমরা কমলা রঙে সাবটাস্ক অনুমানের যোগফল প্রদর্শন করি যে এই মানটি এখনও গল্পে সেট করা হয়নি।
যদি গল্পের একটি অনুমান থাকে , তাহলে এটি সাবটাস্ক অনুমানের যোগফলের সাথে মিলে যায় কিনা তা পরীক্ষা করুন:
এই শর্তগুলির শব্দগুলি বিভ্রান্তিকর হতে পারে, তাই আসুন একটি স্কিমে তাদের প্রকাশ করি।
স্ট্রাকচার ফিচার ব্যবহার করা হয়েছে
একটি কোড উদাহরণ
with isEstimated = storypoints != undefined: with childrenSum = sum#children{storypoints}: with isStory = issueType = "Story": with isErr = isStory AND childrenSum != storypoints: with color = if isStory : if isEstimated : if isErr : "red" else "green" else "orange": if isEstimated : """{color:$color}$storypoints{color} ${if isErr :""" ($childrenSum)"""}""" else """{color:$color}$childrenSum{color}"""
কোডে ডাইভ করার আগে, আসুন আমাদের স্কিমটিকে আরও একটি "কোড-মত" উপায়ে রূপান্তরিত করি যা বোঝার জন্য আমাদের কী ভেরিয়েবল দরকার।
এই স্কিম থেকে আমরা দেখতে পাই যে আমাদের প্রয়োজন হবে:
শর্ত ভেরিয়েবল:
পাঠ্য রঙের একটি পরিবর্তনশীল - রঙ
অনুমানের দুটি ভেরিয়েবল:
তদুপরি, রঙের পরিবর্তনশীলটি বেশ কয়েকটি শর্তের উপরও নির্ভর করে, উদাহরণস্বরূপ, একটি অনুমানের প্রাপ্যতার উপর এবং লাইনে টাস্কের ধরণের উপর (নীচের স্কিমটি দেখুন)।
সুতরাং, রঙ নির্ধারণ করতে, আমাদের আরেকটি শর্ত ভেরিয়েবলের প্রয়োজন হবে, isStory, যা নির্দেশ করে যে টাস্ক টাইপটি Story কিনা।
এসপি ভেরিয়েবল (স্টোরিপয়েন্ট) হবে স্ট্যান্ডার্ড, মানে এটি স্বয়ংক্রিয়ভাবে উপযুক্ত জিরা ফিল্ডে ম্যাপ করবে। আমাদের বাকি ভেরিয়েবলগুলিকে নিজেদের দ্বারা সংজ্ঞায়িত করা উচিত এবং সেগুলি আমাদের কাছে স্থানীয় হবে।
এখন কোডে স্কিমগুলো বাস্তবায়ন করার চেষ্টা করা যাক। প্রথমে চলুন সব ভেরিয়েবল সংজ্ঞায়িত করা যাক।
with isEstimated = storypoints != undefined: with childrenSum = sum#children{storypoints}: with isStory = issueType = "Story": with isErr = isStory AND childrenSum != storypoints:
লাইনগুলি একই সিনট্যাক্স স্কিম দ্বারা একত্রিত হয়: কীওয়ার্ড সহ, পরিবর্তনশীল নাম এবং লাইনের শেষে কোলন চিহ্ন ":"।
সঙ্গে কীওয়ার্ড স্থানীয় ভেরিয়েবল (এবং কাস্টম ফাংশন, কিন্তু একটি পৃথক উদাহরণে আরও বেশি) বোঝাতে ব্যবহৃত হয়। এটি সূত্রটিকে বলে যে পরবর্তী একটি পরিবর্তনশীল যা ম্যাপ করার প্রয়োজন নেই। কোলন ":" পরিবর্তনশীল সংজ্ঞার শেষে পতাকাঙ্কিত করে।
এইভাবে, আমরা isEstimated ভেরিয়েবল তৈরি করি (অনুস্মারক, সেই ক্ষেত্রে গুরুত্বপূর্ণ নয়)। গল্পের পয়েন্ট ক্ষেত্রটি পূরণ হয়েছে কিনা তার উপর নির্ভর করে আমরা এতে 1 বা 0 সংরক্ষণ করব। স্টোরিপয়েন্ট ভেরিয়েবলটি স্বয়ংক্রিয়ভাবে ম্যাপ করা হয়েছে কারণ আমরা এর আগে একই নামের স্থানীয় ভেরিয়েবল তৈরি করিনি (যেমন, স্টোরিপয়েন্টের সাথে = … :)।
অনির্ধারিত ভেরিয়েবল কোন কিছুর অস্তিত্বহীনতাকে বোঝায় (অন্যান্য ভাষায় নাল, NaN এবং এর মতো)। অতএব, অভিব্যক্তি storypoints != undefined একটি প্রশ্ন হিসাবে পড়া যেতে পারে: "গল্প পয়েন্ট ক্ষেত্র পূরণ করা হয়?"।
এর পরে, আমাদের সমস্ত শিশুর কাজের গল্পের পয়েন্টগুলির যোগফল নির্ধারণ করা উচিত। এটি করার জন্য, আমরা একটি স্থানীয় পরিবর্তনশীল তৈরি করি: ChildrenSum.
with childrenSum = sum#children{storypoints}:
এই যোগফল একত্রিতকরণ ফাংশনের মাধ্যমে গণনা করা হয়। (আপনি অফিসিয়াল ডকুমেন্টেশনের মত ফাংশন সম্পর্কে পড়তে পারেন।) সংক্ষেপে, বর্তমান দৃশ্যের শ্রেণিবিন্যাসকে বিবেচনায় রেখে, কাঠামো বিভিন্ন কার্য সম্পাদন করতে পারে।
আমরা যোগফল ফাংশন ব্যবহার করি, এবং এটি ছাড়াও, "#" চিহ্ন ব্যবহার করে, আমরা স্পষ্টীকরণ শিশুদের পাস করি, যা যোগফলের গণনাকে শুধুমাত্র বর্তমান লাইনের যেকোনো শিশুর কাজের জন্য সীমাবদ্ধ করে। কোঁকড়া বন্ধনীতে, আমরা কোন ক্ষেত্রটি সংক্ষিপ্ত করতে চাই তা নির্দেশ করি — আমাদের স্টোরিপয়েন্টে একটি অনুমান প্রয়োজন।
পরবর্তী স্থানীয় ভেরিয়েবল, isStory, একটি শর্ত সংরক্ষণ করে: বর্তমান লাইনের টাস্ক টাইপটি একটি গল্প কিনা।
with isStory = issueType = "Story":
আমরা ইস্যু টাইপ ভেরিয়েবলের দিকে ফিরে যাই, যা অতীতের উদাহরণ থেকে পরিচিত, অর্থাৎ, টাস্কের ধরন যা পছন্দসই ফিল্ডে নিজে থেকেই ম্যাপ করে। আমরা এটি করছি কারণ এটি একটি স্ট্যান্ডার্ড ভেরিয়েবল এবং আমরা পূর্বে এর মাধ্যমে এটিকে সংজ্ঞায়িত করিনি।
এখন আসুন isErr ভেরিয়েবলকে সংজ্ঞায়িত করা যাক - এটি সাবটাস্ক যোগফল এবং গল্পের অনুমানের মধ্যে একটি অসঙ্গতির সংকেত দেয়।
with isErr = isStory AND childrenSum != storypoints:
এখানে আমরা isStory এবং ChildrenSum লোকাল ভেরিয়েবল ব্যবহার করছি যা আমরা আগে তৈরি করেছি। একটি ত্রুটি সংকেত করার জন্য, আমাদের একই সাথে দুটি শর্ত পূরণ করতে হবে: সমস্যার ধরন হল Story (isStory) এবং (AND) শিশুদের পয়েন্টের যোগফল (childrenSum) টাস্কে (গল্পবিন্দু) সেট অনুমানের সমান (!=) নয় ) JQL-এর মতো, আমরা শর্ত তৈরি করার সময় লিঙ্ক শব্দ ব্যবহার করতে পারি, যেমন AND বা OR।
দ্রষ্টব্য, প্রতিটি স্থানীয় ভেরিয়েবলের জন্য লাইনের শেষে একটি ":" চিহ্ন রয়েছে। ভেরিয়েবলকে সংজ্ঞায়িত করে এমন সমস্ত ক্রিয়াকলাপের পরে এটি শেষ হওয়া উচিত। উদাহরণস্বরূপ, যদি আমাদের একটি ভেরিয়েবলের সংজ্ঞাকে কয়েকটি লাইনে ভাঙতে হয়, তবে কোলন ":" শুধুমাত্র শেষ অপারেশনের পরে স্থাপন করা হয়। কালার ভেরিয়েবলের উদাহরণের মতো — টেক্সটের রঙ।
with color = if isStory : if isEstimated : if isErr : "red" else "green" else "orange":
এখানে আমরা প্রচুর ":" দেখতে পাই, কিন্তু তারা বিভিন্ন ভূমিকা পালন করে। isStory এর পরে কোলন isStory অবস্থার ফলাফল। আসুন নির্মাণটি স্মরণ করি: যদি শর্ত: ফলাফল। আসুন এই নির্মাণটিকে আরও জটিল আকারে উপস্থাপন করি, যা একটি পরিবর্তনশীলকে সংজ্ঞায়িত করে।
with variable = (if condition: (if condition2 : result2 else result3) ):
দেখা যাচ্ছে যে if condition2 : result2 else result3 হল, যেমনটি ছিল, প্রথম শর্তের ফলাফল, এবং একেবারে শেষে একটি কোলন আছে “:”, যা ভেরিয়েবলের সংজ্ঞা সম্পূর্ণ করে।
প্রথম নজরে, রঙের সংজ্ঞা জটিল বলে মনে হতে পারে, যদিও প্রকৃতপক্ষে, আমরা উদাহরণের শুরুতে উপস্থাপিত রঙের সংজ্ঞা স্কিমটি এখানে বর্ণনা করেছি। এটা ঠিক যে প্রথম অবস্থার ফলস্বরূপ, আরেকটি শর্ত শুরু হয় - একটি নেস্টেড অবস্থা, এবং এটিতে আরেকটি।
কিন্তু চূড়ান্ত ফলাফল পূর্বে উপস্থাপিত স্কিম থেকে সামান্য ভিন্ন।
if isEstimated : """{color:$color}$storypoints{color} ${if isErr :""" ($childrenSum)"""}""" else """{color:$color}$childrenSum{color}"""
আমাদের কোডে দুবার “{color}$sp'' লিখতে হবে না, যেমনটি স্কিমে ছিল; আমরা জিনিস সম্পর্কে স্মার্ট হতে হবে. শাখায়, যদি টাস্কটির একটি অনুমান থাকে, তাহলে আমরা সর্বদা {color: $color}$storypoints{color} (অর্থাৎ, প্রয়োজনীয় রঙে গল্পের পয়েন্টে শুধুমাত্র একটি অনুমান) প্রদর্শন করব এবং যদি কোনও ত্রুটি থাকে, তাহলে একটি স্থানের পরে, আমরা সাবটাস্ক অনুমানের যোগফলের সাথে লাইনটি পরিপূরক করব: ($childrenSum)।
কোন ত্রুটি না থাকলে, এটি যোগ করা হবে না। আমি আপনার দৃষ্টি আকর্ষণ করছি যে এখানে কোন “:” চিহ্ন নেই, যেহেতু আমরা একটি পরিবর্তনশীলকে সংজ্ঞায়িত করি না, তবে একটি শর্তের মাধ্যমে চূড়ান্ত ফলাফল প্রদর্শন করি।
আমরা নিচের ছবিতে “∑SP (mod)” ফিল্ডে আমাদের কাজের মূল্যায়ন করতে পারি। স্ক্রিনশটটি বিশেষভাবে দুটি অতিরিক্ত ক্ষেত্র দেখায়:
এই উদাহরণগুলির সাহায্যে, আমরা কাঠামোর ভাষার প্রধান বৈশিষ্ট্যগুলি বিশ্লেষণ করেছি যা আপনাকে বেশিরভাগ সমস্যার সমাধান করতে সাহায্য করবে। আসুন এখন আরও দুটি দরকারী বৈশিষ্ট্য দেখুন, আমাদের ফাংশন এবং অ্যারে। আমরা দেখব কিভাবে আমাদের নিজস্ব কাস্টম ফাংশন তৈরি করা যায়।
কখনও কখনও একটি স্প্রিন্টে অনেকগুলি কাজ থাকে এবং আমরা সেগুলিতে ছোট পরিবর্তনগুলি মিস করতে পারি। উদাহরণস্বরূপ, আমরা একটি নতুন সাবটাস্ক মিস করতে পারি বা গল্পগুলির একটি পরবর্তী পর্যায়ে চলে গেছে। কাজগুলির সাম্প্রতিক গুরুত্বপূর্ণ পরিবর্তনগুলি সম্পর্কে আমাদের অবহিত করার জন্য একটি টুল থাকলে ভাল হবে৷
আমরা গতকাল থেকে তিন ধরনের টাস্ক স্ট্যাটাস পরিবর্তনে আগ্রহী: আমরা টাস্কে কাজ শুরু করেছি, একটি নতুন টাস্ক হাজির হয়েছে, টাস্কটি বন্ধ হয়ে গেছে। অতিরিক্তভাবে, এটি দেখতে কার্যকর হবে যে কাজটি "করবে না" রেজোলিউশনের সাথে বন্ধ করা হয়েছে।
এটি করার জন্য, আমরা সাম্প্রতিক পরিবর্তনগুলির জন্য দায়ী ইমোজিগুলির একটি স্ট্রিং সহ একটি ক্ষেত্র তৈরি করব৷ উদাহরণস্বরূপ, যদি একটি টাস্ক গতকাল তৈরি করা হয় এবং আমরা এটিতে কাজ শুরু করি, তাহলে এটি দুটি ইমোজি দিয়ে চিহ্নিত করা হবে: "প্রগতিতে আছে" এবং "নতুন কাজ"।
আমাদের কেন এমন একটি কাস্টম ক্ষেত্র দরকার, যদি বেশ কয়েকটি অতিরিক্ত ক্ষেত্র প্রদর্শিত হতে পারে, উদাহরণস্বরূপ, "প্রগতিতে" স্থিতিতে স্থানান্তরের তারিখ বা একটি পৃথক "রেজোলিউশন" ক্ষেত্রে? উত্তরটি সহজ — লোকেরা পাঠ্যের চেয়ে ইমোজিগুলি সহজ এবং দ্রুত উপলব্ধি করে, যা বিভিন্ন ক্ষেত্রে অবস্থিত এবং বিশ্লেষণ করা প্রয়োজন। সূত্রটি এক জায়গায় সবকিছু সংগ্রহ করবে এবং আমাদের জন্য এটি বিশ্লেষণ করবে, যা আমাদের আরও দরকারী জিনিসগুলির জন্য প্রচেষ্টা এবং সময় বাঁচাবে।
চলুন নির্ধারণ করা যাক বিভিন্ন ইমোজি কিসের জন্য দায়ী:
স্ট্রাকচার ফিচার ব্যবহার করা হয়েছে
একটি কোড উদাহরণ
if defined(issueType): with now = now(): with daysScope = 1.3: with workDaysBetween(today, from)= ( with weekends = (Weeknum(today) - Weeknum(from)) * 2: HOURS_BETWEEN(from;today)/24 - weekends ): with daysAfterCreated = workDaysBetween(now,created): with daysAfterStart = workDaysBetween(now,latestTransitionToProgress): with daysAfterDone = workDaysBetween(now, resolutionDate): with isWontDo = resolution = "Won't Do": with isRecentCreated = daysAfterCreated >= 0 and daysAfterCreated <= daysScope and not(resolution): with isRecentWork = daysAfterStart >= 0 and daysAfterStart <= daysScope : with isRecentDone = daysAfterDone >= 0 and daysAfterDone <= daysScope : concat( if isRecentCreated : "*️⃣", if isRecentWork : "🚀", if isRecentDone : "✅", if isWontDo : "❌")
সমাধান একটি বিশ্লেষণ
শুরু করার জন্য, আমাদের আগ্রহের ঘটনাগুলি নির্ধারণ করার জন্য আমাদের প্রয়োজনীয় বৈশ্বিক ভেরিয়েবলগুলি সম্পর্কে চিন্তা করা যাক। আমাদের জানতে হবে, যদি গতকাল থেকে:
নতুন ম্যাপিং ভেরিয়েবলের পাশাপাশি ইতিমধ্যে বিদ্যমান ভেরিয়েবলগুলি ব্যবহার করা আমাদের এই সমস্ত শর্তগুলি পরীক্ষা করতে সহায়তা করবে।
কোডে এগিয়ে যাওয়া যাক। প্রথম লাইনটি একটি শর্ত দিয়ে শুরু হয় যা পরীক্ষা করে যে টাস্ক টাইপ বিদ্যমান কিনা।
if defined(issueType):
এটি বিল্ট-ইন সংজ্ঞায়িত ফাংশনের মাধ্যমে করা হয়, যা নির্দিষ্ট ক্ষেত্রের অস্তিত্ব পরীক্ষা করে। চেকটি সূত্রের গণনাকে অপ্টিমাইজ করার জন্য তৈরি করা হয়েছে।
লাইনটি একটি টাস্ক না হলে আমরা অকেজো গণনার সাথে স্ট্রাকচার লোড করব না। দেখা যাচ্ছে যে if এর পরে সমস্ত কোডের ফলাফল, মানে, if (শর্ত: ফলাফল) নির্মাণের দ্বিতীয় অংশ। এবং যদি শর্ত পূরণ না হয়, তাহলে কোডটিও কাজ করবে না।
এখন = now(): এর সাথে পরবর্তী লাইনটিও গণনা অপ্টিমাইজ করার জন্য প্রয়োজন। কোডে আরও, আমাদের বর্তমান তারিখের সাথে বিভিন্ন তারিখের তুলনা করতে হবে বেশ কয়েকবার। একই গণনা একাধিকবার না করার জন্য, আমরা এই তারিখটি একবার গণনা করব এবং এটিকে এখন একটি স্থানীয় পরিবর্তনশীল করব।
আমাদের “গতকাল” আলাদা করে রাখলে ভালো হবে। সুবিধাজনক "গতকাল" অভিজ্ঞতাগতভাবে 1.3 দিনে পরিণত হয়েছে৷ আসুন এটিকে একটি ভেরিয়েবলে পরিণত করি: দিনস্কোপ = 1.3: সহ।
এখন আমাদের অনেকবার দুই তারিখের মধ্যে দিনের সংখ্যা গণনা করতে হবে। উদাহরণস্বরূপ, বর্তমান তারিখ এবং কাজ শুরুর তারিখের মধ্যে। অবশ্যই, একটি অন্তর্নির্মিত DAYS_BETWEEN ফাংশন আছে, যা আমাদের জন্য উপযুক্ত বলে মনে হচ্ছে। কিন্তু, যদি টাস্কটি, উদাহরণস্বরূপ, শুক্রবার তৈরি করা হয়, তাহলে সোমবার আমরা একটি নতুন টাস্কের বিজ্ঞপ্তি দেখতে পাব না, যেহেতু বাস্তবে 1.3 দিনের বেশি সময় কেটে গেছে। উপরন্তু, DAYS_BETWEEN ফাংশন শুধুমাত্র মোট দিনের সংখ্যা গণনা করে (অর্থাৎ, 0.5 দিন 0 দিনে পরিণত হবে), যা আমাদের জন্য উপযুক্ত নয়।
আমরা একটি প্রয়োজনীয়তা তৈরি করেছি — আমাদের এই তারিখগুলির মধ্যে কার্যদিবসের সঠিক সংখ্যা গণনা করতে হবে; এবং একটি কাস্টম ফাংশন এটি আমাদের সাহায্য করবে।
এটির সংজ্ঞায়িত সিনট্যাক্স একটি স্থানীয় পরিবর্তনশীল সংজ্ঞায়িত করার জন্য সিনট্যাক্সের অনুরূপ। একমাত্র পার্থক্য এবং একমাত্র সংযোজন হল প্রথম বন্ধনীতে আর্গুমেন্টের ঐচ্ছিক গণনা। দ্বিতীয় বন্ধনীতে এমন ক্রিয়াকলাপ রয়েছে যা সঞ্চালিত হবে যখন আমাদের ফাংশনটি কল করা হবে। ফাংশনের এই সংজ্ঞাটি একমাত্র সম্ভব নয়, তবে আমরা এটি ব্যবহার করব (অন্যগুলি অফিসিয়াল ডকুমেন্টেশনে পাওয়া যাবে)।
with workDaysBetween(today, from)= ( with weekends = (Weeknum(today) - Weeknum(from)) * 2: HOURS_BETWEEN(from;today)/24 - weekends ):
আমাদের কাস্টম workDaysBetween ফাংশন আজকের এবং তারিখের মধ্যে কাজের দিনগুলি গণনা করবে, যেগুলি আর্গুমেন্ট হিসাবে পাস করা হয়েছে। ফাংশনের যুক্তি খুবই সহজ: আমরা ছুটির দিনের সংখ্যা গণনা করি এবং তারিখগুলির মধ্যে মোট দিনের সংখ্যা থেকে বিয়োগ করি।
ছুটির দিনের সংখ্যা গণনা করার জন্য, আমাদের খুঁজে বের করতে হবে আজ থেকে এবং এর মধ্যে কত সপ্তাহ কেটে গেছে। এটি করার জন্য, আমরা প্রতিটি সপ্তাহের সংখ্যার মধ্যে পার্থক্য গণনা করি। আমরা Weeknum ফাংশন থেকে এই সংখ্যাটি পাব, যা বছরের শুরু থেকে সপ্তাহের সংখ্যা আমাদের প্রদান করে। এই পার্থক্যটিকে দুই দ্বারা গুণ করলে আমরা ছুটির দিনগুলির সংখ্যা পাই।
এরপর, HOURS_BETWEEN ফাংশনটি আমাদের তারিখের মধ্যে ঘন্টার সংখ্যা গণনা করে। দিনের সংখ্যা পেতে আমরা ফলাফলটিকে 24 দ্বারা ভাগ করি এবং এই সংখ্যা থেকে ছুটির দিনগুলি বিয়োগ করি, তাই আমরা তারিখগুলির মধ্যে কাজের দিনগুলি পাই৷
আমাদের নতুন ফাংশন ব্যবহার করে, আসুন অক্জিলিয়ারী ভেরিয়েবলের একটি গুচ্ছ সংজ্ঞায়িত করি। উল্লেখ্য যে সংজ্ঞার কিছু তারিখ হল গ্লোবাল ভেরিয়েবল, যা আমরা উদাহরণের শুরুতে বলেছি।
with daysAfterCreated = workDaysBetween(now,created): with daysAfterStart = workDaysBetween(now,latestTransitionToProgress): with daysAfterDone = workDaysBetween(now, resolutionDate):
কোডটিকে পড়ার জন্য সুবিধাজনক করতে, চলুন এমন ভেরিয়েবলগুলিকে সংজ্ঞায়িত করা যাক যা শর্তগুলির ফলাফল সংরক্ষণ করে।
with isWontDo = resolution = "Won't Do": with isRecentCreated = daysAfterCreated >= 0 and daysAfterCreated <= daysScope and not(resolution): with isRecentWork = daysAfterStart >= 0 and daysAfterStart <= daysScope : with isRecentDone = daysAfterDone >= 0 and daysAfterDone <= daysScope :
isRecentCreated ভেরিয়েবলের জন্য, আমি একটি ঐচ্ছিক শর্ত যোগ করেছি এবং না(রেজোলিউশন), যা আমাকে ভবিষ্যত লাইনকে সহজ করতে সাহায্য করে, কারণ যদি টাস্কটি ইতিমধ্যেই বন্ধ থাকে, তাহলে আমি এর সাম্প্রতিক সৃষ্টি সম্পর্কে তথ্যে আগ্রহী নই।
চূড়ান্ত ফলাফল কনক্যাট ফাংশনের মাধ্যমে তৈরি করা হয়, লাইনগুলিকে সংযুক্ত করে।
concat( if isRecentCreated : "*️⃣", if isRecentWork : "🚀", if isRecentDone : "✅", if isWontDo : "❌")
দেখা যাচ্ছে যে ইমোজিটি তখনই লাইনে থাকবে যখন কন্ডিশনের ভেরিয়েবলটি 1 এর সমান হবে। এইভাবে, আমাদের লাইন একই সাথে টাস্কে স্বাধীন পরিবর্তনগুলি প্রদর্শন করতে পারে।
আমরা ছুটি ছাড়াই কর্মদিবস গণনার বিষয়ে আলোচনা করেছি। এর সাথে সম্পর্কিত আরেকটি সমস্যা রয়েছে, যা আমরা আমাদের শেষ উদাহরণে বিশ্লেষণ করব এবং একই সাথে অ্যারেগুলির সাথে পরিচিত হব।
মাঝে মাঝে আমরা জানতে চাই ছুটির দিন বাদ দিয়ে একটি কাজ কতদিন ধরে চলছে। এটি প্রয়োজনীয়, উদাহরণস্বরূপ, প্রকাশিত সংস্করণ বিশ্লেষণ করার জন্য। আমাদের কেন ছুটি দরকার তা বোঝার জন্য। একটি বাদে সোমবার থেকে বৃহস্পতিবার এবং অন্যটি শুক্রবার থেকে সোমবার পর্যন্ত চলছিল। এই ধরনের পরিস্থিতিতে, আমরা বলতে পারি না যে কাজগুলি সমতুল্য, যদিও ক্যালেন্ডার দিনের পার্থক্য আমাদের বিপরীত বলে।
দুর্ভাগ্যবশত, স্ট্রাকচার "বাক্সের বাইরে" কীভাবে ছুটির দিনগুলিকে উপেক্ষা করতে হয় তা জানে না, এবং জিরা সেটিংস নির্বিশেষে "টাইম ইন স্ট্যাটাস..." বিকল্পের ক্ষেত্রটি একটি ফলাফল তৈরি করে — এমনকি যদি শনিবার এবং রবিবার ছুটির দিন হিসাবে নির্দিষ্ট করা হয়।
ফলস্বরূপ, আমাদের লক্ষ্য হল কার্যদিবসের সঠিক সংখ্যা গণনা করা, ছুটির দিনগুলি উপেক্ষা করা এবং এই সময়ে স্থিতি পরিবর্তনের প্রভাব বিবেচনা করা।
এবং স্ট্যাটাস এর সাথে কি করার আছে? আমাকে উত্তর দিন. ধরুন আমরা গণনা করেছি যে 10 মার্চ থেকে 20 মার্চের মধ্যে, টাস্কটি তিন দিন ধরে কাজ করছে। কিন্তু এই 3 দিনের মধ্যে, এটি একদিনের জন্য বিরতিতে এবং দেড় দিনের জন্য পর্যালোচনায় ছিল। দেখা যাচ্ছে যে টাস্কটি মাত্র অর্ধেক দিনের জন্য কাজে ছিল।
স্ট্যাটাসগুলির মধ্যে পরিবর্তন করার সমস্যার কারণে আগের উদাহরণের সমাধানটি আমাদের জন্য উপযুক্ত নয়, কারণ কাস্টম workDaysBetween ফাংশনটি শুধুমাত্র দুটি নির্বাচিত তারিখের মধ্যে সময়কে বিবেচনা করে।
এই সমস্যা বিভিন্ন উপায়ে সমাধান করা যেতে পারে। উদাহরণের পদ্ধতিটি পারফরম্যান্সের দিক থেকে সবচেয়ে ব্যয়বহুল, তবে ছুটির দিন এবং স্থিতি গণনার ক্ষেত্রে সবচেয়ে সঠিক। মনে রাখবেন যে এটির বাস্তবায়ন শুধুমাত্র 7.4 (ডিসেম্বর 2021) এর চেয়ে পুরনো স্ট্রাকচার সংস্করণে কাজ করে।
সুতরাং, সূত্রের পিছনের ধারণাটি নিম্নরূপ:
এইভাবে, আমরা টাস্কে কাজের সঠিক সময় পাব, ছুটির দিন এবং অতিরিক্ত স্ট্যাটাসের মধ্যে পরিবর্তন উপেক্ষা করে।
স্ট্রাকচার ফিচার ব্যবহার করা হয়েছে
একটি কোড উদাহরণ
if defined(issueType) : if status != "Open" : with finishDate = if toQA != Undefined : toQA else if toDone != Undefined : toDone else now(): with startDate = DEFAULT(toProgress, toDone): with statusWeekendsCount(dates, status) = ( dates.filter(x -> weekday(x) > 5 and historical_value(this,"status",x)=status).size() ): with overallDays = round(hours_between(startDate,finishDate)/24): with sequenceArray = SEQUENCE(0,overallDays): with datesArray = sequenceArray.map(DATE_ADD(startDate,$,"day")): with progressWeekends = statusWeekendsCount(datesArray, "in Progress"): with progressDays = (timeInProgress/86400000 - progressWeekends).round(1): with color = if( progressDays = 0 ; "gray" ; progressDays > 0 and progressDays <= 2.5; "green" ; progressDays > 2.5 and progressDays <= 4; "orange" ; progressDays > 4; "red" ): """{color:$color}$progressDays d{color}"""
সমাধান একটি বিশ্লেষণ
কোডে আমাদের অ্যালগরিদম স্থানান্তর করার আগে, আসুন স্ট্রাকচারের জন্য গণনাকে সহজ করে দেই।
if defined(issueType) : if status != "Open" :
যদি লাইনটি একটি টাস্ক না হয় বা এর স্থিতি "ওপেন" হয়, তাহলে আমরা সেই লাইনগুলি এড়িয়ে যাব। আমরা শুধুমাত্র কাজ করতে আগ্রহী যে কাজ শুরু করা হয়েছে.
তারিখগুলির মধ্যে দিনের সংখ্যা গণনা করতে, আমাদের প্রথমে এই তারিখগুলি নির্ধারণ করতে হবে: শেষ তারিখ এবং শুরুর তারিখ।
with finishDate = if toQA != Undefined : toQA else if toDone != Undefined : toDone else now(): with startDate = DEFAULT(toProgress, toDone):
আমরা ধরে নেব যে টাস্ক সমাপ্তির তারিখ (finishDate) হল:
কাজ শুরুর তারিখ শুরুর তারিখ "প্রগতিতে" স্থিতিতে রূপান্তরের তারিখ দ্বারা নির্ধারিত হয়। এমন কিছু ঘটনা আছে যখন কাজটি কাজের পর্যায়ে না গিয়েই বন্ধ হয়ে যায়। এই ধরনের ক্ষেত্রে, আমরা শেষ তারিখটিকে শুরুর তারিখ হিসাবে বিবেচনা করি, তাই, ফলাফলটি 0 দিন।
আপনি হয়ত অনুমান করেছেন toQA, toDone এবং toProgress হল ভেরিয়েবল যেগুলিকে প্রথম এবং পূর্ববর্তী উদাহরণগুলির মতো উপযুক্ত স্থিতিতে ম্যাপ করা দরকার৷
আমরা নতুন DEFAULT(toProgress, toDone) ফাংশনও দেখতে পাচ্ছি। এটি toProgress এর একটি মান আছে কিনা তা পরীক্ষা করে এবং যদি না থাকে তবে এটি toDone ভেরিয়েবলের মান ব্যবহার করে।
এরপরে স্ট্যাটাস উইকেন্ডসকাউন্ট কাস্টম ফাংশনের সংজ্ঞা আসে, তবে আমরা পরে এটিতে ফিরে যাব, যেহেতু এটি তারিখের তালিকার সাথে ঘনিষ্ঠভাবে সম্পর্কিত। এই তালিকার সংজ্ঞায় সরাসরি যাওয়া ভাল, যাতে পরে আমরা বুঝতে পারি কীভাবে এটিতে আমাদের ফাংশন প্রয়োগ করতে হয়।
আমরা নিম্নলিখিত ফর্মে তারিখগুলির একটি তালিকা পেতে চাই: [শুরু তারিখ (আসুন 11.03 বলা যাক), 12.03, 13.03, 14.03 … সমাপ্তির তারিখ]। কাঠামোতে আমাদের জন্য সমস্ত কাজ করবে এমন কোনও সাধারণ ফাংশন নেই। তাহলে চলুন একটি কৌশল অবলম্বন করা যাক:
এখন, আসুন দেখি কিভাবে আমরা কোডে এটি বাস্তবায়ন করতে পারি। আমরা অ্যারে সঙ্গে কাজ করা হবে.
with overallDays = round(hours_between(startDate,finishDate)/24): with sequenceArray = SEQUENCE(0,overallDays): with datesArray = sequenceArray.map(DATE_ADD(startDate,$,"day")):
একটি টাস্কের কাজ কত দিন লাগবে তা আমরা গণনা করি। আগের উদাহরণের মতো, 24 দ্বারা বিভাজনের মাধ্যমে এবং hours_between(startDate,finishDate) ফাংশন। ফলাফল সামগ্রিক দিন পরিবর্তনশীল লেখা হয়.
আমরা sequenceArray ভেরিয়েবলের আকারে সংখ্যা ক্রমগুলির একটি অ্যারে তৈরি করি। এই অ্যারেটি SEQUENCE(0,overallDays) ফাংশনের মাধ্যমে তৈরি করা হয়েছে, যা কেবলমাত্র 0 থেকে সামগ্রিক দিনে একটি ক্রম সহ কাঙ্ক্ষিত আকারের একটি অ্যারে তৈরি করে৷
এরপরে আসে ম্যাজিক। অ্যারে ফাংশনগুলির মধ্যে একটি হল মানচিত্র। এটি অ্যারের প্রতিটি উপাদানে নির্দিষ্ট অপারেশন প্রয়োগ করে।
আমাদের কাজ হল প্রতিটি সংখ্যার সাথে শুরুর তারিখ যোগ করা (অর্থাৎ দিনের সংখ্যা)। DATE_ADD ফাংশন এটি করতে পারে, এটি নির্দিষ্ট তারিখে একটি নির্দিষ্ট সংখ্যক দিন, মাস বা বছর যোগ করে।
এটি জেনে, আসুন স্ট্রিংটি ডিক্রিপ্ট করি:
with datesArray = sequenceArray.map(DATE_ADD(startDate, $,"day"))
সিকোয়েন্স অ্যারের প্রতিটি উপাদানের জন্য, .map() ফাংশনটি DATE_ADD(শুরু তারিখ, $, "দিন") প্রযোজ্য।
DATE_ADD-এর আর্গুমেন্টে কী পাস করা হয়েছে তা দেখা যাক। প্রথম জিনিস হল startDate, যে তারিখে কাঙ্খিত সংখ্যা যোগ করা হবে। এই সংখ্যাটি দ্বিতীয় আর্গুমেন্ট দ্বারা নির্দিষ্ট করা হয়েছে, কিন্তু আমরা $ দেখতে পাচ্ছি।
$ প্রতীক একটি অ্যারে উপাদান নির্দেশ করে। কাঠামোটি বুঝতে পারে যে DATE_ADD ফাংশনটি একটি অ্যারেতে প্রয়োগ করা হয়েছে, এবং তাই $ এর পরিবর্তে কাঙ্ক্ষিত অ্যারে উপাদান থাকবে (অর্থাৎ, 0, 1, 2 …)।
শেষ আর্গুমেন্ট "দিন" হল একটি ইঙ্গিত যে আমরা একটি দিন যোগ করি, যেহেতু ফাংশনটি একটি দিন, মাস এবং বছর যোগ করতে পারে, আমরা যা নির্দিষ্ট করি তার উপর নির্ভর করে।
এইভাবে, datesArray ভেরিয়েবল কাজ শুরু থেকে তার সমাপ্তি পর্যন্ত তারিখের অ্যারে সংরক্ষণ করবে।
আসুন কাস্টম ফাংশনে ফিরে যাই যা আমরা মিস করেছি। এটি অতিরিক্ত দিনগুলিকে ফিল্টার করবে এবং অবশিষ্টগুলি গণনা করবে৷ আমরা এই অ্যালগরিদমটি উদাহরণের একেবারে শুরুতে বর্ণনা করেছি, কোড বিশ্লেষণ করার আগে, যেমন অনুচ্ছেদ 3 এবং 4-এ ছুটির দিন এবং স্ট্যাটাস ফিল্টার করার বিষয়ে।
with statusWeekendsCount(dates, status) = ( dates.filter(x -> weekday(x) > 5 and historical_value(this,"status",x)=status).size() ):
আমরা কাস্টম ফাংশনে দুটি আর্গুমেন্ট পাস করব: তারিখগুলির একটি অ্যারে, আসুন এটিকে তারিখ বলি, এবং প্রয়োজনীয় স্থিতি — স্থিতি। আমরা স্থানান্তরিত তারিখ অ্যারেতে .filter() ফাংশন প্রয়োগ করি, যা ফিল্টার অবস্থার মধ্য দিয়ে যাওয়া অ্যারের মধ্যে শুধুমাত্র সেই রেকর্ডগুলি রাখে। আমাদের ক্ষেত্রে, তাদের মধ্যে দুটি আছে, এবং তারা এবং এর মাধ্যমে একত্রিত হয়। ফিল্টারটির পরে, আমরা .size() দেখতে পাচ্ছি, এটিতে সমস্ত অপারেশন সম্পন্ন হওয়ার পরে এটি অ্যারের আকার ফেরত দেয়।
যদি আমরা এক্সপ্রেশনকে সরলীকরণ করি, তাহলে আমরা এরকম কিছু পাব: array.filter(condition1 এবং condition2).size()। সুতরাং, ফলস্বরূপ, আমরা আমাদের জন্য উপযুক্ত দিনগুলির সংখ্যা পেয়েছি, অর্থাৎ, সেই দিনগুলি যেগুলি শর্ত অতিক্রম করেছে।
আসুন উভয় অবস্থার উপর ঘনিষ্ঠভাবে নজর দেওয়া যাক:
x -> weekday(x) > 5 and historical_value(this,"status",x)=status
এক্সপ্রেশন x -> ফিল্টার সিনট্যাক্সের একটি অংশ, যা নির্দেশ করে যে আমরা অ্যারের উপাদানটিকে x বলব। অতএব, প্রতিটি শর্তে x প্রদর্শিত হয় ($ এর সাথে এটির মতোই)। এটা দেখা যাচ্ছে যে x হস্তান্তরিত তারিখ অ্যারে থেকে প্রতিটি তারিখ।
প্রথম শর্ত, সপ্তাহের দিন(x) > 5, তারিখ x-এর সপ্তাহের দিন (অর্থাৎ, প্রতিটি উপাদান) 5-এর বেশি হতে হবে — এটি হয় শনিবার (6) বা রবিবার (7)।
দ্বিতীয় শর্ত ঐতিহাসিক_মান ব্যবহার করে।
historical_value(this,"status",x) = status
এটি সংস্করণ 7.4 এর কাঠামোর একটি বৈশিষ্ট্য।
ফাংশনটি কাজের ইতিহাস অ্যাক্সেস করে এবং নির্দিষ্ট ক্ষেত্রে একটি নির্দিষ্ট তারিখের জন্য অনুসন্ধান করে। এই ক্ষেত্রে, আমরা "স্থিতি" ক্ষেত্রে তারিখ x অনুসন্ধান করছি। এই ভেরিয়েবলটি ফাংশন সিনট্যাক্সের অংশ মাত্র, এটি স্বয়ংক্রিয়ভাবে ম্যাপ করা হয় এবং লাইনে বর্তমান কাজটি উপস্থাপন করে।
এইভাবে, কন্ডিশনে, আমরা স্থানান্তরিত স্ট্যাটাস আর্গুমেন্ট এবং "স্ট্যাটাস" ফিল্ডের তুলনা করি, যেটি অ্যারের প্রতিটি তারিখ x-এর জন্য history_value ফাংশন দ্বারা ফেরত দেওয়া হয়। যদি তারা মিলে যায়, তাহলে তালিকায় এন্ট্রি থেকে যায়।
চূড়ান্ত স্পর্শ হল পছন্দসই স্থিতিতে দিনের সংখ্যা গণনা করতে আমাদের ফাংশনের ব্যবহার:
with progressWeekends = statusWeekendsCount(datesArray, "in Progress"): with progressDays = (timeInProgress/86400000 - progressWeekends).round(1):
প্রথমে, আসুন জেনে নেওয়া যাক আমাদের datesArray-এ “প্রগতিতে চলছে” স্ট্যাটাস সহ কত দিনের ছুটি আছে। অর্থাৎ, আমরা আমাদের তারিখের তালিকা এবং কাঙ্খিত স্থিতি কাস্টম ফাংশন স্ট্যাটাস উইকেন্ডসকাউন্টে পাস করি। ফাংশনটি সমস্ত সপ্তাহের দিন এবং সমস্ত ছুটি নিয়ে যায় যেখানে টাস্কের স্থিতি "প্রগতিতে" স্থিতি থেকে আলাদা এবং তালিকায় অবশিষ্ট দিনের সংখ্যা ফেরত দেয়।
তারপর আমরা timeInProgress ভেরিয়েবল থেকে এই পরিমাণ বিয়োগ করি, যেটিকে আমরা “Time in status …” বিকল্পের মাধ্যমে ম্যাপ করি।
সংখ্যা 86400000 হল ভাজক যা মিলিসেকেন্ডকে দিনে পরিণত করবে। .round(1) ফাংশনটি ফলাফলকে দশম পর্যন্ত রাউন্ড করার জন্য প্রয়োজন, উদাহরণস্বরূপ “4.1”, অন্যথায় আপনি এই ধরনের এন্ট্রি পেতে পারেন: “4.0999999 …”।
টাস্কের দৈর্ঘ্য নির্দেশ করতে, আমরা রঙ পরিবর্তনশীল প্রবর্তন করি। টাস্কে কত দিন কেটেছে তার উপর নির্ভর করে আমরা এটি পরিবর্তন করব।
with color = if( progressDays = 0 ; "gray" ; progressDays > 0 and progressDays <= 2.5; "green" ; progressDays > 2.5 and progressDays <= 4; "orange" ; progressDays > 4; "red" ):
এবং গণনা করা দিনের ফলাফল সহ চূড়ান্ত লাইন:
"""{color:$color}$progressDays d{color}"""
আমাদের ফলাফল নিচের ছবির মত দেখাবে।
যাইহোক, একই সূত্রে, আপনি যেকোনো স্ট্যাটাসের সময় প্রদর্শন করতে পারেন। উদাহরণস্বরূপ, যদি আমরা আমাদের কাস্টম ফাংশনে "পজ" স্ট্যাটাস পাস করি এবং "টাইম ইন … — পজ" এর মাধ্যমে timeInProgress ভেরিয়েবল ম্যাপ করি, তাহলে আমরা বিরামের সঠিক সময় গণনা করব।
আপনি স্ট্যাটাস একত্রিত করতে পারেন এবং একটি এন্ট্রি করতে পারেন যেমন “wip: 3.2d | rev: 12d”, অর্থাৎ কাজের সময় এবং পর্যালোচনার সময় গণনা করুন। আপনি শুধুমাত্র আপনার কল্পনা এবং আপনার কর্মপ্রবাহ দ্বারা সীমাবদ্ধ.
আমরা এই সূত্র ভাষার একটি বিস্তৃত সংখ্যক বৈশিষ্ট্য উপস্থাপন করেছি যা আপনাকে অনুরূপ কিছু করতে বা জিরা কাজগুলি বিশ্লেষণ করার জন্য সম্পূর্ণ নতুন এবং আকর্ষণীয় কিছু লিখতে সহায়তা করবে।
আমি আশা করি নিবন্ধটি আপনাকে সূত্রগুলি বের করতে সাহায্য করেছে, বা অন্ততপক্ষে আপনাকে এই বিষয়ে আগ্রহী করেছে। আমি দাবি করি না যে আমার কাছে "সেরা কোড এবং অ্যালগরিদম" আছে, তাই উদাহরণগুলি কীভাবে উন্নত করা যায় সে সম্পর্কে আপনার ধারণা থাকলে, আপনি সেগুলি ভাগ করলে আমি খুশি হব!
অবশ্যই, আপনাকে বুঝতে হবে যে ALM ওয়ার্কস ডেভেলপারদের চেয়ে ভাল সূত্র সম্পর্কে কেউ আপনাকে বলবে না। অতএব, আমি তাদের ডকুমেন্টেশন এবং ওয়েবিনারের লিঙ্ক সংযুক্ত করছি। এবং আপনি যদি কাস্টম ক্ষেত্রগুলির সাথে কাজ করা শুরু করেন তবে আপনি অন্য কোন বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন তা দেখতে প্রায়ই সেগুলি পরীক্ষা করে দেখুন৷