paint-brush
ডেটা ক্লাস থেকে এক্সেল পর্যন্ত: টীকা সহ একটি জাভা ম্যাপার তৈরি করাদ্বারা@sergeidzeboev
2,778 পড়া
2,778 পড়া

ডেটা ক্লাস থেকে এক্সেল পর্যন্ত: টীকা সহ একটি জাভা ম্যাপার তৈরি করা

দ্বারা Sergei Dzeboev18m2023/09/24
Read on Terminal Reader
Read this story w/o Javascript

অতিদীর্ঘ; পড়তে

এক্সেল রিপোর্ট তৈরি করার জন্য একটি কাস্টম জাভা লাইব্রেরি তৈরি করেছে, নমনীয় সেল স্টাইলিং, সূত্র তৈরি এবং গতিশীল প্রতিবেদন তৈরির জন্য টীকা ব্যবহার করে। প্রক্রিয়াটির মধ্যে Apache POI ব্যবহার করা, বিশেষ টীকা তৈরি করা এবং এক্সেল রিপোর্ট তৈরির জন্য একটি পরিষেবা বাস্তবায়ন করা জড়িত। উপযোগী পদ্ধতিটি সহজ, নির্ভুলতা এবং ভবিষ্যতের কাস্টমাইজেশনের জন্য সম্ভাব্যতা প্রদান করে।
featured image - ডেটা ক্লাস থেকে এক্সেল পর্যন্ত: টীকা সহ একটি জাভা ম্যাপার তৈরি করা
Sergei Dzeboev HackerNoon profile picture
0-item

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


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


আমার উচ্চাকাঙ্ক্ষা ছিল জ্যাকসনের মতো একটি লাইব্রেরি ডিজাইন করা, যা টীকা দ্বারা নির্দেশিত হিসাবে ডেটা ক্লাসের তালিকাকে একটি এক্সেল নথিতে রূপান্তর করতে টীকা ব্যবহার করবে।


আমি আমার তৈরি করা লাইব্রেরি শেয়ার করতে চাই, আশা করি এটি অন্যদের উপকার করতে পারে বা তাদের অনন্য কাজের জন্য তাদের নিজস্ব ম্যাপার তৈরি করতে অনুপ্রাণিত করতে পারে। আসুন এটি অর্জন করতে কীভাবে জাভাতে এই জাতীয় ডেটা ম্যাপার তৈরি করা যায় তা অন্বেষণ করি:


এটা থেকে:

 void demoReport() { var excelMapper = new ExcelMapperImpl(); var fileName = "demo-out-" + LocalTime.now() + ".xlsx"; List<Demo> demos = generateDemos(); try (Workbook workbook = excelMapper.createWorkbookFromObject(demos); var fileOutputStream = new FileOutputStream(fileName)) { workbook.write(fileOutputStream); } }


টীকা সংজ্ঞায়িত করা

আসুন এক্সেল ম্যাপিংয়ের জন্য প্রয়োজনীয় প্রধান উপাদানগুলি সনাক্ত করি। এর মূলে, আমাদের একটি এক্সেল কলাম প্রয়োজন। প্রতিবেদনের এই মৌলিক উপাদানটি প্রতিটি সারিতে কলামের নাম এবং সংশ্লিষ্ট মানটি স্পষ্টভাবে প্রদর্শন করা উচিত।


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


নিছক ডেটা সেলের বাইরে, আমাদের সহজেই সেল স্টাইলিং পরিচালনা করার জন্য বৈশিষ্ট্যগুলিকে একীভূত করা উচিত।


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

 @Retention(RetentionPolicy.RUNTIME) public @interface ColumnExcelStyle { ExcelColumnDataFormat cellTypePattern() default ExcelColumnDataFormat.NONE; IndexedColors cellColor() default IndexedColors.AUTOMATIC; boolean isWrapText() default false; boolean isCentreAlignment() default false; boolean isFramed() default true; ExcelColumnFont fontName() default ExcelColumnFont.DEFAULT; short fontSize() default -1; boolean isFontBold() default false; ExcelColumnCellTextColor fontColor() default ExcelColumnCellTextColor.AUTOMATIC; }


প্রতিবেদন তৈরির জন্য গুরুত্বপূর্ণ প্রাথমিক শৈলী উপাদানগুলি বৈশিষ্ট্য হিসাবে প্রকাশ করা হয়। এটি অনুসরণ করে, একটি এক্সেল কলাম টীকা শুরু করা যেতে পারে:

 @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface ColumnExcel { String[] applyNames() default {}; int position(); ColumnExcelStyle headerStyle() default @ColumnExcelStyle( fontColor = ExcelColumnCellTextColor.BLACK, isCentreAlignment = true, isFontBold = true, fontSize = 14, isWrapText = true); ColumnExcelStyle cellStyle() default @ColumnExcelStyle; }


এই টীকাটি সম্ভাব্য কলামের নাম (এক্সেল থেকে ম্যাপিংয়ের জন্য) এবং একটি বাধ্যতামূলক ক্ষেত্র - ' position ' অন্তর্ভুক্ত করে। এটি কলামের স্থান নির্ধারণ করবে এবং সূত্র গণনার ক্ষেত্রে সহায়ক হবে। উপরন্তু, এটি শিরোনাম এবং কক্ষ উভয়ের শৈলীর বিশদ বিবরণ দেবে।


চমৎকার। এখন, এক্সেল সূত্রের জন্য নির্দিষ্ট একটি টীকা তৈরি করা যাক। সারির অবস্থানের উপর একটি গতিশীল সূত্র কন্টিনজেন্টের প্রত্যাশা করে, এই টীকাটি পদ্ধতিগুলির জন্য একচেটিয়া হবে:

 @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ColumnExcelFormula { String name() default ""; int position(); ColumnExcelStyle headerStyle() default @ColumnExcelStyle( fontColor = ExcelColumnCellTextColor.BLACK, isCentreAlignment = true, isFontBold = true, fontSize = 14, isWrapText = true); ColumnExcelStyle cellStyle() default @ColumnExcelStyle; }


পরিশেষে, আসুন সমাপ্তি সূত্রের জন্য একটি টীকা প্রবর্তন করা যাক, যা সাধারণত এক্সেলের চূড়ান্ত সারি দখল করে, একটি কলামের জন্য ক্রমবর্ধমান ফলাফলের সারাংশ বা চিত্রিত করে। প্রদত্ত যে সূত্রের টীকাটি শুধুমাত্র পদ্ধতিগুলির জন্য তার প্রযোজ্যতাকে বাধ্যতামূলক করে:

 @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface ColumnExcelTotalFormula { boolean useValue() default false; int position(); ColumnExcelStyle cellStyle() default @ColumnExcelStyle; }


Apache POI দিয়ে একটি এক্সেল রিপোর্টিং পরিষেবা তৈরি করা

সমস্ত প্রয়োজনীয় টীকা তৈরি করার পরে, একটি পরিষেবা ক্লাস তৈরি করা পরবর্তী ধাপে পরিণত হয়। ব্যবহৃত মূল লাইব্রেরি Apache POI হবে, .xls এবং .xlsx ফাইলগুলির সাথে কাজ করার জন্য কার্যকর৷ এই ক্লাসটি একটি এক্সেল রিপোর্ট তৈরি করতে টীকাগুলির বৈশিষ্ট্যগুলি ব্যবহার করবে৷


প্রাথমিক পদ্ধতি ইনপুট হিসাবে বস্তুর একটি তালিকা গ্রহণ করে এবং একটি প্রস্তুত ওয়ার্কবুক প্রদান করে।


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

 <T> Workbook createWorkbookFromObject(List<T> reportObjects) { return createWorkbookFromObject(reportObjects, 0, "Report"); } <T> Workbook createWorkbookFromObject(List<T> reportObjects, int startRowNumber, String sheetName) { ... }


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


যদি একটি নাম অনুপস্থিত থাকে, ক্লাস ক্ষেত্রের নাম একটি বিকল্প হিসাবে পরিবেশন করতে পারে:

 private <T> void createHeaderFromDeclaredExcelColumns(Row row, Class<T> clazz, PropertyDescriptor propertyDescriptor) { try { Field field = clazz.getDeclaredField(propertyDescriptor.getName()); ColumnExcel columnExcel = field.getDeclaredAnnotation(ColumnExcel.class); if (nonNull(columnExcel)) { String headerName = columnExcel.applyNames().length > 0 ? columnExcel.applyNames()[0] : field.getName(); createHeader(row, columnExcel.position(), headerName, columnExcel.headerStyle()); } } catch (NoSuchFieldException e) { log.debug(e.getLocalizedMessage()); } }


হেডার তৈরি করার সময়, প্রতিটি কক্ষে একটি শৈলী বরাদ্দ করতে ভুলবেন না। স্টাইল প্যারামিটারগুলি @ColumnExcelStyle টীকা থেকে প্রাপ্ত করা যেতে পারে:

 private void createHeader(Row row, int position, String name, ColumnExcelStyle columnExcelStyle) { Cell cell = row.createCell(position); cell.setCellValue(name); setCellFormatting(cell, columnExcelStyle); row.getSheet().autoSizeColumn(cell.getColumnIndex()); }


প্রদত্ত অ্যারে থেকে ডেটার উপর ভিত্তি করে প্রক্রিয়াটি তারপর রিপোর্টে সারি তৈরিতে পরিণত হয়। ডেটার উপর পুনরাবৃত্তি করে, ধারাবাহিক সারিগুলি গঠিত হয়:

 for (T report : reportObjects) { Row bodyRow = sheet.createRow(proceedRowNumber); createCellsFromDeclaredExcelColumns(bodyRow, report); proceedRowNumber++; }


ক্ষেত্রগুলিতে সরাসরি অ্যাক্সেস দেওয়ার পরিবর্তে গেটারদের ব্যবহার করার জন্য সম্পত্তি বর্ণনাকারী সংগ্রহ করা হয়:

 private <T> void createCellsFromDeclaredExcelColumns(Row row, T tObject) { try { PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(tObject.getClass()).getPropertyDescriptors(); for (var propertyDescriptor : propertyDescriptors) { createCellFromDeclaredExcelColumns(row, tObject, propertyDescriptor); } } catch (IntrospectionException ex) { log.debug(ex.getLocalizedMessage()); } }


সম্পত্তি বর্ণনাকারীর সাথে, একটি ঘর গঠিত হয়:

 private <T> void createCellFromDeclaredExcelColumns(Row row, T tObject, PropertyDescriptor propertyDescriptor) { try { Field field = tObject.getClass().getDeclaredField(propertyDescriptor.getName()); Method readMethod = propertyDescriptor.getReadMethod(); ColumnExcel columnExcel = field.getDeclaredAnnotation(ColumnExcel.class); if (nonNull(columnExcel)) { Class<?> returnType = readMethod.getReturnType(); Cell cell = row.createCell(columnExcel.position()); Object invokeResult = readMethod.invoke(tObject); if (nonNull(invokeResult)) { defineAndAssignCellValue(returnType, cell, invokeResult, readMethod); } setCellFormatting(cell, columnExcel.cellStyle()); } } catch (NoSuchFieldException | InvocationTargetException | IllegalAccessException e) { log.debug(e.getLocalizedMessage()); } }


এর পরে, আসুন @ColumnExcelFormula টীকা প্রক্রিয়াকরণের দিকে আমাদের মনোযোগ দিন। ফর্মুলা তৈরি করা একটি ক্ষেত্র থেকে একটি মান বের করার চেয়ে সামান্য বেশি জটিল প্রমাণ করে। একটি পদ্ধতি একটি সূত্র তৈরি করবে বলে আশা করা হচ্ছে, যা পরবর্তীতে কোষে বরাদ্দ করা হয়।


পদ্ধতিটি ধারাবাহিকভাবে একটি স্ট্রিং ফেরত দেবে এবং সারি নম্বরটিকে একটি যুক্তি হিসাবে গ্রহণ করবে, সংলগ্ন কক্ষ থেকে সঠিক ডেটা ব্যবহার নিশ্চিত করবে।


সুতরাং, নির্দিষ্ট সূত্রের সাথে সেল গঠনের আগে এই শর্তগুলি পূরণ হয়েছে তা যাচাই করার জন্য এটি হ্যান্ডলারের উপর পড়ে:

 private <T> void createCellFromDeclaredExcelFormula(Row row, T tObject, Method readMethod) throws IllegalAccessException, InvocationTargetException { ColumnExcelFormula columnExcelFormula = readMethod.getDeclaredAnnotation(ColumnExcelFormula.class); if (columnExcelFormula != null) { Class<?> returnType = readMethod.getReturnType(); Cell cell = row.createCell(columnExcelFormula.position()); if (returnType.isAssignableFrom(String.class)) { cell.setCellFormula((String) readMethod.invoke(tObject, row.getRowNum())); } else { log.debug(" Return type for the method: " + readMethod.getName() + " with @ColumnExcelFormula annotation has to be String " + "and now it's: " + returnType.getName() + " method is ignored for the reason"); } setCellFormatting(cell, columnExcelFormula.cellStyle()); } }


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


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


প্রারম্ভিক সারির সংখ্যার বিধান অত্যাবশ্যক, পুরো কলামের জন্য সামগ্রিক ফলাফলের সুবিধা দেয় এমন একটি সূত্র তৈরি করতে পদ্ধতিটিকে সক্ষম করে:

 private <T> void createTotalFormula(Class<T> tClazz, Row row, int firstRowNum) { Method[] methods = tClazz.getDeclaredMethods(); for (Method method : methods) { ColumnExcelTotalFormula columnExcelTotalFormula = method.getAnnotation(ColumnExcelTotalFormula.class); if (columnExcelTotalFormula != null && method.getReturnType().isAssignableFrom(String.class) && method.getParameters().length == 2 && Modifier.isStatic(method.getModifiers()) && !Modifier.isPrivate(method.getModifiers()) ) { String cellFormula = (String) method.invoke(tClazz, firstRowNum, row.getRowNum()); Cell cell = row.createCell(columnExcelTotalFormula.position()); cell.setCellFormula(cellFormula); if (columnExcelTotalFormula.useValue()) { cell = applyFormulasValue(cell); } setCellFormatting(cell, columnExcelTotalFormula.cellStyle()); } } }


একটি প্রতিবেদন তৈরি করা

প্রধান কার্যকারিতা এখন জায়গায় আছে, এবং এটি কার্যকরভাবে দেখার সময়। এর কার্যকারিতা প্রদর্শনের জন্য একটি সাধারণ প্রতিবেদন তৈরি করা যাক। এর জন্য, আসুন একটি ' Sales ' ক্লাস তৈরি করি এবং সমস্ত প্রয়োজনীয় টীকা অন্তর্ভুক্ত করি:

 @Data @Accessors(chain = true) public class Sales { @ColumnExcel( position = 0, applyNames = {"Date"}, headerStyle = @ColumnExcelStyle( fontColor = WHITE, cellColor = DARK_BLUE, isCentreAlignment = true), cellStyle = @ColumnExcelStyle( cellColor = GREY_25_PERCENT, cellTypePattern = DATE)) private LocalDate date; @ColumnExcel( position = 1, applyNames = {"Sold"}, headerStyle = @ColumnExcelStyle( fontColor = WHITE, cellColor = DARK_BLUE, isCentreAlignment = true), cellStyle = @ColumnExcelStyle( cellColor = GREY_25_PERCENT)) private Integer sold; @ColumnExcel( position = 2, applyNames = {"Price Per Unit (USD)"}, headerStyle = @ColumnExcelStyle( fontColor = WHITE, cellColor = DARK_BLUE, isCentreAlignment = true), cellStyle = @ColumnExcelStyle( cellColor = GREY_25_PERCENT, cellTypePattern = USD)) private Double pricePerUnit; @ColumnExcelFormula( position = 3, name = "Total Sales (USD)", headerStyle = @ColumnExcelStyle( fontColor = WHITE, cellColor = DARK_BLUE, isCentreAlignment = true), cellStyle = @ColumnExcelStyle( cellColor = GREY_25_PERCENT, cellTypePattern = USD)) public String sales(int rowNum) { return new CellAddress(rowNum, 1).formatAsString() + "*" + new CellAddress(rowNum, 2).formatAsString(); } @ColumnExcelTotalFormula( position = 0, cellStyle = @ColumnExcelStyle( cellColor = LIGHT_BLUE)) public static String total(int firstRowNum, int lastRowNum) { return "CONCATENATE(\"Total\")"; } @ColumnExcelTotalFormula( position = 1, cellStyle = @ColumnExcelStyle( cellColor = LIGHT_BLUE)) public static String unitsSold(int firstRowNum, int lastRowNum) { return "SUM(" + new CellAddress(firstRowNum, 1).formatAsString() + ":" + new CellAddress(lastRowNum - 1, 1).formatAsString() + ")"; } @ColumnExcelTotalFormula( position = 3, cellStyle = @ColumnExcelStyle( isCentreAlignment = false, cellColor = LIGHT_BLUE, cellTypePattern = USD)) public static String totalSales(int firstRowNum, int lastRowNum) { return "SUM(" + new CellAddress(firstRowNum, 3).formatAsString() + ":" + new CellAddress(lastRowNum - 1, 3).formatAsString() + ")"; } }


ক্লাসে তিনটি ক্ষেত্র রয়েছে: date , sold এবং pricePerUnit । উপরন্তু, এটির একটি বিক্রয় সূত্র এবং মোটের সাথে একটি সমাপনী লাইন রয়েছে: unitsSold এবং totalSales । ক্ষেত্রগুলি @ColumnExcel টীকা ব্যবহার করে, কলামের অবস্থান এবং নাম নির্দেশ করে।


@ColumnExcelStyle টীকা হেডার এবং পৃথক ডেটা সেল উভয়ের জন্য শৈলী সংজ্ঞায়িত করে:

 @ColumnExcel( position = 0, applyNames = {"Date"}, headerStyle = @ColumnExcelStyle( fontColor = WHITE, cellColor = DARK_BLUE, isCentreAlignment = true), cellStyle = @ColumnExcelStyle( cellColor = GREY_25_PERCENT, cellTypePattern = DATE) )


পূর্বে আলোচনা করা হয়েছে, একটি সূত্র তৈরি করার সময়, পদ্ধতিটি অবশ্যই সারি সংখ্যা নির্দেশ করে এমন একটি প্যারামিটার গ্রহণ করবে। এই প্রয়োজনীয়তা পদ্ধতির স্বাক্ষরে স্পষ্ট:

 public String sales(int rowNum) { return new CellAddress(rowNum, 1).formatAsString() + "*" + new CellAddress(rowNum, 2).formatAsString(); }


সারি নম্বর এবং কলাম সূচকগুলি দেওয়া হলে, কোনও নির্দিষ্ট সূত্র তৈরি করা সম্ভবপর হয়ে ওঠে।


ক্লাসের মধ্যে, উপসংহারের সূত্রগুলির জন্য উদ্দিষ্ট পদ্ধতিগুলি স্থির এবং দুটি পরামিতি প্রয়োজন: প্রারম্ভিক সারির সংখ্যা এবং শেষ সারির সংখ্যা:

 public static String unitsSold(int firstRowNum, int lastRowNum) { return "SUM(" + new CellAddress(firstRowNum, 1).formatAsString() + ":" + new CellAddress(lastRowNum - 1, 1).formatAsString() + ")"; }


এখন, পদ্ধতিটি চালু করা যাক:

 void salesReport() { var excelMapper = new ExcelMapperImpl(); var fileName = "sales-out-" + LocalTime.now() + ".xlsx"; List<Sales> sales = List.of( new Sales().setDate(LocalDate.of(2023, 1, 1)) .setSold(50) .setPricePerUnit(10d), new Sales().setDate(LocalDate.of(2023, 1, 2)) .setSold(40) .setPricePerUnit(11d), new Sales().setDate(LocalDate.of(2023, 1, 3)) .setSold(55) .setPricePerUnit(9d); try (Workbook workbook = excelMapper.createWorkbookFromObject(sales); var fileOutputStream = new FileOutputStream(fileName)) { workbook.write(fileOutputStream); } }


এবং উত্পন্ন রিপোর্ট পরীক্ষা করুন:

উপসংহার

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


অতএব, পরবর্তী সময়ে একটি উপযুক্ত গ্রন্থাগার অধরা, একটি ব্যক্তিগতকৃত একটি বিকাশের বিবেচনায় উপকারী হতে পারে।


স্বাভাবিকভাবেই, এই নিবন্ধে কোডের প্রতিটি লাইন উপস্থাপন করা সম্ভবপর ছিল না; এইভাবে, ম্যাপারের অপারেশনের জন্য প্রয়োজনীয় শুধুমাত্র প্রাথমিক পদ্ধতিগুলি হাইলাইট করা হয়েছিল। সম্পূর্ণ কোড আমার GitHub পৃষ্ঠায় উপলব্ধ।