// ============================================ // IMPROVED GEMINI 2.5 PRO CONTENT GENERATOR v11.0 (FIXED) // ============================================ // --- CONFIGURATION --- const API_KEYS = [ "AIzaSyDaTlIfAvE16d1tcUpYf36W2AvJLyvfpCA", "AIzaSyCX5cyvEMHNVmIhLyJy9k5F4gK3Z_12nRc", "AIzaSyAglH7ziQNK8tOBcfsq773rGsmyR0flG4g", "AIzaSyCfKsRAOzmQRTtEFNMBGXfjuK6-M9ZywJ0", "AIzaSyCk2sDgg1ZEz-y5hDROGtowZ9QCLHC8jVs", "AIzaSyDOKrEV4vF9uG8BV7oD-wDBDSmj2FnxoOQ", "AIzaSyCJhjc-5wDP7PPAki_7TAYtS4_9H4oBfMY", "AIzaSyAW-BUcALvA5XJ0yHPhIKRodi-RMfmxlUw", "AIzaSyBrM9nnTT7Jx_qmZztMGOYWI-aliQYsOAI", "AIzaSyChyd0s7vdQYoP6IMekoVoT5LWKfj8VVt4", "AIzaSyB-7H-96RTJFMOT0B-rb33IRQlRgCtOJQA", "AIzaSyCNBVH71NRmjB0DVQJrR5hU8y08ZNw0Qeo", "AIzaSyCGyIWP-uWnS_z2o9Fhjvp-Sn2h-Qtlkbc", "AIzaSyBJs5gIIGdKIQr3loHXlvuifs6P3ESmL0o", "AIzaSyC12QXQfJlYJCLIgui1HWZDvYJBx630MZ8", "AIzaSyCvRL9NFA3bnIR7vDLFz2kldlcow55C1BM", "AIzaSyADGc0k0iLYDi9C7V4SjicPGV_4rZXcGpk", ]; // Track which API key is currently in use let currentKeyIndex = 0; const CONFIG = { model: "gemini-flash-latest", version: "v1beta", temperature: 0.7, top_p: 0.9, // Reduced max tokens for faster generation while maintaining quality maxOutputTokens: 64000, // Reduced from 65000 retryDelay: 1000 // 1 second delay between retries }; const COLUMNS = { KEYWORD: 0, NLP_OUTLINE: 1, INTRO: 2, CONTENT: 3, FAQS: 4, META_DESC: 5, TITLE: 6, SECONDARY_KEYWORD: 7 }; const CACHE_KEY_LOGS = 'GEMINI_EXEC_LOGS'; const CACHE_KEY_STATE = 'GEMINI_EXEC_STATE'; // --- MENU & UI --- function onOpen() { SpreadsheetApp.getUi().createMenu('πŸš€ Advanced Content Generator') .addItem('πŸ“Š Open Advanced Sidebar', 'openAdvancedSidebar') .addItem('πŸ—‘οΈ Clear Cache/Reset', 'clearCacheAndState') .addToUi(); } function openAdvancedSidebar() { const html = HtmlService.createHtmlOutput(getAdvancedSidebarHtml()) .setTitle('πŸš€ Advanced Content Generator v11.0'); SpreadsheetApp.getUi().showSidebar(html); } // ============================================ // REAL-TIME LOGGING & STATE MANAGEMENT (FIXED) // ============================================ function addLog(message, level = 'info') { const cache = CacheService.getUserCache(); const timestamp = new Date().toLocaleTimeString('en-US', { hour12: false }); const logEntry = { timestamp: timestamp, level: level, message: message }; // Get existing logs from cache let logs = []; const cachedLogs = cache.get(CACHE_KEY_LOGS); if (cachedLogs) { try { logs = JSON.parse(cachedLogs); } catch(e) {} } // Add new log and keep only last 40 to prevent Cache limits logs.push(logEntry); if (logs.length > 40) logs.shift(); // Save back to cache (expires in 6 hours) cache.put(CACHE_KEY_LOGS, JSON.stringify(logs), 21600); // Also log to internal console for debugging console.log(`[${level.toUpperCase()}] ${message}`); } function getLogs() { const cache = CacheService.getUserCache(); const cachedLogs = cache.get(CACHE_KEY_LOGS); return cachedLogs ? JSON.parse(cachedLogs) : []; } function clearLogs() { CacheService.getUserCache().remove(CACHE_KEY_LOGS); } function updateState(updates) { const cache = CacheService.getUserCache(); let state = getProcessingStatus(); // Get current or default // Merge updates const newState = { ...state, ...updates }; cache.put(CACHE_KEY_STATE, JSON.stringify(newState), 21600); return newState; } function getProcessingStatus() { const cache = CacheService.getUserCache(); const cachedState = cache.get(CACHE_KEY_STATE); const defaultState = { isProcessing: false, currentTask: 'Idle', currentRow: 0, totalRows: 0, rowsCompleted: 0, progress: 0, currentKeyword: '' }; if (cachedState) { try { return JSON.parse(cachedState); } catch(e) { return defaultState; } } return defaultState; } function clearCacheAndState() { const cache = CacheService.getUserCache(); cache.remove(CACHE_KEY_LOGS); cache.remove(CACHE_KEY_STATE); addLog('Cache cleared. Ready to start.', 'info'); } // ============================================ // ROW MANAGEMENT // ============================================ function getAvailableRows() { const sheet = SpreadsheetApp.getActiveSheet(); const lastRow = sheet.getLastRow(); const availableRows = []; // Assuming headers are in row 1, data starts row 2 if (lastRow < 2) return []; const data = sheet.getRange(2, 1, lastRow - 1, 8).getValues(); for (let i = 0; i < data.length; i++) { const rowNum = i + 2; // Actual sheet row number if (data[i][0] && data[i][0].toString().trim() !== "") { availableRows.push({ row: rowNum, keyword: data[i][0].toString(), secondaryKeyword: data[i][7] ? data[i][7].toString() : "", nlpOutline: data[i][1] ? data[i][1].toString() : "" }); } } return availableRows; } // ============================================ // CORE GENERATION LOGIC // ============================================ function startGeneration(selectedRows) { // Reset logs and state at start clearCacheAndState(); if (!selectedRows || selectedRows.length === 0) { return { success: false, message: 'No rows selected' }; } updateState({ isProcessing: true, totalRows: selectedRows.length, rowsCompleted: 0, progress: 0, currentTask: 'Starting initialization...' }); addLog(`πŸš€ Starting generation for ${selectedRows.length} rows`, 'info'); // We loop here. In a pro script, we might use Triggers for very long lists, // but for <10 rows, a simple loop works if we keep it under 6 mins. try { processBatch(selectedRows); return { success: true, message: 'Batch completed successfully' }; } catch (e) { addLog(`πŸ’₯ Critical Error: ${e.toString()}`, 'error'); updateState({ isProcessing: false, currentTask: 'Error Stopped' }); return { success: false, message: e.toString() }; } } function processBatch(rowNumbers) { const sheet = SpreadsheetApp.getActiveSheet(); for (let i = 0; i < rowNumbers.length; i++) { const rowNum = rowNumbers[i]; const rowData = getRowData(rowNum); // Update State updateState({ currentRow: rowNum, currentKeyword: rowData.keyword, progress: Math.round((i / rowNumbers.length) * 100), currentTask: `Processing Row ${rowNum}: ${rowData.keyword}` }); addLog(`πŸ“ START ROW ${rowNum}: "${rowData.keyword}"`, 'info'); // Create a results object to store all generated content const results = { intro: null, content: null, faqs: null, meta: null, title: null }; // 1. TITLE - Generate first as it might influence other content addLog(`⏳ Generating Title...`, 'info'); results.title = generateTitle(rowData); if (results.title) { sheet.getRange(rowNum, COLUMNS.TITLE + 1).setValue(results.title); addLog(`βœ… Title Saved`, 'success'); } else { addLog(`❌ Failed to generate Title`, 'error'); } // 2. INTRO addLog(`⏳ Generating Intro...`, 'info'); results.intro = generateHTMLIntro(rowData, results.title); if (results.intro) { sheet.getRange(rowNum, COLUMNS.INTRO + 1).setValue(results.intro); addLog(`βœ… Intro Saved`, 'success'); } else { addLog(`❌ Failed to generate Intro`, 'error'); } // 3. CONTENT addLog(`⏳ Generating Main Content (Long Form)...`, 'info'); results.content = generateHTMLContent(rowData, results.intro, results.title); if (results.content) { sheet.getRange(rowNum, COLUMNS.CONTENT + 1).setValue(results.content); addLog(`βœ… Content Saved (${results.content.split(' ').length} words)`, 'success'); } else { addLog(`❌ Failed to generate Content`, 'error'); } // 4. FAQS addLog(`⏳ Generating FAQs...`, 'info'); results.faqs = generateHTMLFAQs(rowData, results.content); if (results.faqs) { sheet.getRange(rowNum, COLUMNS.FAQS + 1).setValue(results.faqs); addLog(`βœ… FAQs Saved`, 'success'); } else { addLog(`❌ Failed to generate FAQs`, 'error'); } // 5. META DESC addLog(`⏳ Generating Meta Description...`, 'info'); results.meta = generateMetaDescription(rowData, results.content, results.title); if (results.meta) { sheet.getRange(rowNum, COLUMNS.META_DESC + 1).setValue(results.meta); addLog(`βœ… Meta Description Saved`, 'success'); } else { addLog(`❌ Failed to generate Meta Description`, 'error'); } // Check if any part failed const failedParts = Object.keys(results).filter(key => !results[key]); if (failedParts.length > 0) { addLog(`⚠️ Row ${rowNum} completed with missing parts: ${failedParts.join(', ')}`, 'warning'); } else { addLog(`πŸŽ‰ Row ${rowNum} Complete - All parts generated successfully`, 'success'); } // Update completion updateState({ rowsCompleted: i + 1 }); } updateState({ isProcessing: false, progress: 100, currentTask: 'All Tasks Completed' }); addLog('🏁 Batch Generation Finished', 'success'); } function getRowData(rowNum) { const sheet = SpreadsheetApp.getActiveSheet(); const row = sheet.getRange(rowNum, 1, 1, 8).getValues()[0]; return { keyword: row[0], nlpOutline: row[1], secondaryKeyword: row[7] }; } // ============================================ // GEMINI API CALLS (FIXED) // ============================================ // Get the next API key in round-robin fashion function getNextApiKey() { const key = API_KEYS[currentKeyIndex]; currentKeyIndex = (currentKeyIndex + 1) % API_KEYS.length; return key; } // Reset API key index to start from the first key function resetApiKeyIndex() { currentKeyIndex = 0; } function callAdvancedGeminiApi(prompt, systemPrompt, taskType) { let attempts = 0; const maxAttempts = API_KEYS.length; // Reset to start with the first key resetApiKeyIndex(); while (attempts < maxAttempts) { try { const apiKey = getNextApiKey(); addLog(`πŸ”‘ Using API key index ${currentKeyIndex} for ${taskType}`, 'info'); // Construct Endpoint for Gemini const url = `https://generativelanguage.googleapis.com/${CONFIG.version}/models/${CONFIG.model}:generateContent?key=${apiKey}`; // Construct Payload with Tools and Thinking Config const payload = { systemInstruction: { parts: [{ text: systemPrompt || 'You are a world-class SEO strategist, copywriter, and knowledge systems engineer with 32 years of experience. You create long-form, Semantic google HCS , authoritative search-first, semantically optimized content. Every output must demonstrate topical authority, E-E-A-T signals, and deliver authentic, knowledge-rich' }] }, contents: [ { role: "user", parts: [{ text: prompt }] } ], // Add Google Search Tool tools: [ { googleSearch: {} } ], generationConfig: { temperature: CONFIG.temperature, maxOutputTokens: CONFIG.maxOutputTokens, // Add Thinking Config (Budget -1 implies auto/max) thinkingConfig: { thinkingBudget: 2000 } } }; const response = UrlFetchApp.fetch(url, { method: "post", contentType: "application/json", payload: JSON.stringify(payload), muteHttpExceptions: true }); const responseCode = response.getResponseCode(); const responseText = response.getContentText(); if (responseCode !== 200) { addLog(`API Error ${responseCode}: ${responseText}`, 'error'); // If rate limited, try with next key if (responseCode === 429) { addLog(`Rate limited on key index ${currentKeyIndex}, trying next key`, 'warning'); attempts++; continue; } // For other errors, also try next key attempts++; continue; } const json = JSON.parse(responseText); if (json.candidates && json.candidates[0].content) { addLog(`βœ… Successfully generated ${taskType}`, 'success'); return json.candidates[0].content.parts[0].text; } else { addLog(`Invalid response format for ${taskType}`, 'error'); attempts++; } } catch (e) { addLog(`API Exception for ${taskType}: ${e.toString()}`, 'error'); attempts++; } // Add delay between retries if (attempts < maxAttempts) { Utilities.sleep(CONFIG.retryDelay); } } addLog(`❌ All API keys exhausted for ${taskType}`, 'error'); return null; } // ============================================ // PROMPT FUNCTIONS (FIXED) // ============================================ function generateHTMLIntro(data, title) { const sys = `You are an SEO content writer with 20+ years of experience. Write EXACTLY two introduction paragraphs each paragraph between only 150-200 words. Each paragraph MUST start DIRECTLY with the primary keyword - no articles or filler phrases inclose in p tag. ${title ? `The title is: "${title}".` : ''} EXPERTISE AREAS: - Semantic SEO and keyword integration in HTML - User intent analysis and matching - Authority building through expert language - Compelling storytelling techniques - Strict HTML formatting with allowed tags only - Do not use * or ** symbols. `; const prompt = `Write a 2-paragraph intro for "${data.keyword}". Include secondary keyword: "${data.secondaryKeyword}". As a pro seo expert generate introduction two parapgraph that: Tone: Maintain a professional yet accessible tone, balancing authority with simplicity. Ensure the language is clear and easy to understand for a general audience (Grade level 7-9) - Naturally integrates all keywords at appropriate density without stuffing. - Focus Keyphrase (Choose a Focus Keyphrase, Use it in Key Positions ) - Keyword Optimization (se the Focus Keyword Naturally, LSI Keywords) - Covers all relevant subtopics, examples, and related entities for full semantic coverage. - Demonstrates authority and expertise (E-E-A-T). - Follow Google’s SEO Guidelines For better Content, ensuring the information is valuable and helpful according to user needs, and free of unnecessary content or filler. - Ensure the output is free of grammar or spelling errors while maintaining readability Easy to Read. - Ensure content remains to the point, focused, and easy to understand words-sentence. make sure each sentence easy to understand clear which have proper meaning, aligning with user intent. - - - Avoid unnecessary expansions, keeping the content easy to understand and use short sentence for better readability. 1. STARTS with the primary keyword naturally in the first sentence 2. Incorporates the secondary keyword naturally 3. Addresses user intent and pain points related to man keyword "${data.keyword}". 4. Establishes authority and credibility 5. Creates curiosity and provides value upfront All content must directly solve user problems Write the content without using AI-style filler words or patterns. Do not use wording that sounds generic, repetitive, or machine-generated. Avoid the following categories completely: – general filler (accurate, comprehensive, detailed, overview, typically, usually, generally) – vague verbs (provide, provided, offering, allows, allow) – weak structure words (process, method, option, tool, resources) – unnecessary formality (context, insight, profile, records maintained by, repository) – content-padding phrases (listed below, as follows, various, multiple, including, contains) . Strictly follow this requirement: your response should not include any of the following words and phrases: meticulous, meticulously, navigating, complexities, realm, understanding, dive, shall, tailored, towards, underpins, everchanging, ever-evolving, the world of, not only, alright, embark, Journey, In today's digital age, hey, game changer, designed to enhance, it is advisable, daunting, when it comes to, in the realm of, amongst, unlock the secrets, unveil the secrets, and robust, diving, elevate, unleash, power, cutting-edge, rapidly, expanding, mastering, excels, harness, imagine, It's important to note, Delve into, Tapestry, Bustling, In summary, Remember that…, Take a dive into, Navigating, Landscape, Testament, In the world of, Realm, Embark, Analogies to being a conductor or to music, Vibrant, Metropolis, Firstly, Moreover, Crucial, To consider, Essential, There are a few considerations, Ensure, It's essential to, Furthermore, Vital, Keen, Fancy, As a professional, However, Therefore, Additionally, Specifically, Generally, Consequently, Importantly, Indeed, Thus, Alternatively, Notably, As well as, Despite, Essentially, While, Unless, Also, Even though, Because, In contrast, Although, In order to, Due to, Even if, Given that, Arguably, You may want to, On the other hand, As previously mentioned, It's worth noting that, To summarize, Ultimately, To put it simply, Promptly, Dive into, In today's digital era, Reverberate, Enhance, Emphasize / Emphasize, Revolutionize, Foster, Remnant, Subsequently, Nestled, Game changer, Labyrinth, Gossamer, Enigma, Whispering, Sights unseen, Sounds unheard, Indelible, My friend, In conclusion, guide, guidelines, addition, era, individuals, Definitive. Guide. CONTENT STRUCTURE TO REFERENCE: ${data.nlpOutline} Generate ONLY the well seo optimze 2 intro paragragh in html p tag.): Start directly with the keyword.`; return cleanHTML(callAdvancedGeminiApi(prompt, sys, 'Intro')); } /// Content Genenration prompts################################# function generateHTMLContent(data, intro, title) { const sys = `You are a world-class SEO strategist, copywriter, and knowledge systems engineer with 32 years of experience. You create long-form, search-first, semantically optimized content that starts with the main keyword in the first sentence or heading. Every output must demonstrate topical authority, E-E-A-T signals, and deliver authentic, knowledge-rich value between 3500-4500 words. make sure give me complete content not skip or stop without complete the content. You never generate fluff, repetitive sentences, or keyword stuffing. Strictly follow this requirement: your response should not include any of the following words and phrases: Definitive, Alternative meticulous, meticulously, navigating, complexities, realm, understanding, dive, shall, tailored, towards, underpins, everchanging, ever-evolving, the world of, not only, alright, embark, Journey, In today's digital age, hey, game changer, designed to enhance, it is advisable, daunting, when it comes to, in the realm of, amongst, unlock the secrets, unveil the secrets, and robust, diving, elevate, unleash, power, cutting-edge, rapidly, expanding, mastering, excels, harness, imagine, It's important to note, Delve into, Tapestry, Bustling, In summary, Remember that…, Take a dive into, Navigating, Landscape, Testament, In the world of, Realm, Embark, Analogies to being a conductor or to music, Vibrant, Metropolis, Firstly, Moreover, Crucial, To consider, Essential, There are a few considerations, Ensure, It's essential to, Furthermore, Vital, Keen, Fancy, As a professional, However, Therefore, Additionally, Specifically, Generally, Consequently, Importantly, Indeed, Thus, Alternatively, Notably, As well as, Despite, Essentially, While, Unless, Also, Even though, Because, In contrast, Although, In order to, Due to, Even if, Given that, Arguably, You may want to, On the other hand, As previously mentioned, It's worth noting that, To summarize, Ultimately, To put it simply, Promptly, Dive into, In today's digital era, Reverberate, Enhance, Emphasize / Emphasize, Revolutionize, Foster, Remnant, Subsequently, Nestled, Game changer, Labyrinth, Gossamer, Enigma, Whispering, Sights unseen, Sounds unheard, Indelible, My friend, In conclusion, guide, guidelines, addition, era, individuals, Definitive. Guide, Comprehensive, in addition, conclusion, final thought, final word, inshort, Accessing, Differentiating, extensive, signifies, enforcement, information, info, informative etc. All content should be structured with H1, H2, H3, H4, and FAQs as relevant, and written at a 5th-grade reading level for clarity.. SPECIALIZATIONS: - Semantic keyword integration and LSI optimization in HTML - E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) - User intent mapping and satisfaction - Technical accuracy with practical applications - Conversion-optimized content structure with visual engagement - Do not add faqs in this content - Make sure add real offical detail not own wrong add - Do not use * or ** symbols. As a world-class SEO strategist, copywriter, and knowledge systems engineer with 32 years of experience. Make sure this is not a guide but did not use word like this info this gudie, guide etc anywhere in content. SPECIALIZATIONS: - Semantic keyword integration and LSI optimization in HTML - E-E-A-T (Experience, Expertise, Authoritativeness, Trustworthiness) - User intent mapping and satisfaction - Technical accuracy with practical applications - Conversion-optimized content structure - STRICT HTML formatting with allowed tags only - Do not add any fake info anywhere in content`; const prompt = `Your only goal: Create a HIGH-ENGAGEMENT, SEO-DOMINANT content piece (3500-4500 words) that users love to read and Google prioritizes for ranking start with h2 heading. ake sure give me complete content not skip or stop without complete the content. Analyze the following inputs: PRIMARY KEYWORD: "${data.keyword}" SECONDARY KEYWORD: "${data.secondaryKeyword || 'N/A'}" NLP/LSI OUTLINE: "${data.nlpOutline}" INTRODUCTION: "${intro}" ${title ? `Title: "${title}".` : ''} ${intro ? `Existing Intro: ${intro}.` : ''} Generate a COMPREHENSIVE, PRODUCTION-READY SEO page content (3000-4500 words) in STRICT HTML format: CONTENT STRUCTURE REQUIREMENTS (MANDATORY): CRITICAL REQUIREMENTS: do add intor 1. srictly start with H2 heading that includes the primary keyword. 2. EXCLUDE these phrases: "question:", "conclusion:", "intro", "final thought:", "in conclusion:", "to conclude:", "ultimately:", "finally,", "lastly," "FAQ's into" 4. Main H2 heading with keyword 5. 3500-5000 words total 6. Use heading paragraph list table to make the content engaingin and tractive to attract user with best main heading sould be h2 7. Real office location contact block, emails and phone numbers 8. Embedded Google Maps iframe 9. Real resources, PDFs, dates, prices 10. Use real value price date etc where need and valuable, help the user 1. VISUAL ENGAGEMENT FORMULA: - USE Lists (ul/ol) and Tables for maximum readability - Maximum 2-3 sentences per paragraph - Break content with subheadings every 120-150 words - Use numbered lists for processes and rankings - Create comparison tables for options, tools, methods - Do not use * or ** symbols. Paragraphs max 120–150 words Sentences avg 20 words or fewer 30%+ transition words Active voice heavily preferred Keyword + entities placed in key positions (H1, H2, first 100 words, summaries) Subheadings every 120–200 words Scannable formatting: lists, bullets, steps, pros/cons, FAQs All content must directly solve user problems Write the content without using AI-style filler words or patterns. Do not use wording that sounds generic, repetitive, or machine-generated. CONTENT REQUIREMENTS: Produce a new SEO-optimized a well-optimized, user-focused content piece that is not only tailored to ranking high on search engines but also provides significant value to the user, making it difficult to de-rank in the long run and content word cout stickly between (3500-4500 words) that: - Follows a hierarchical structure: H1 (title), H2 for main sections, H3/H4 for subtopics ul/ol for list, , for best layout table if need. - Paragraphs max 120–150 words - Sentences avg 20 words or fewer - 30%+ transition words - Active voice heavily preferred - Keyword + entities placed in key positions (H1, H2, first 100 words, summaries) - Scannable formatting: lists, bullets, steps, pros/cons, FAQs - All content must directly solve user problems - content without using AI-style filler words or patterns. - Do not use wording that sounds generic, repetitive, or machine-generated. - Short Paragraphs: Keep paragraphs under 150 words for readability and user experience. - Tone: Maintain a professional yet accessible tone, balancing authority with simplicity. Ensure the language is clear and easy to understand for a general audience (Grade level 7-9) - Naturally integrates all keywords at appropriate density without stuffing. - Focus Keyphrase (Choose a Focus Keyphrase, Use it in Key Positions ) - Keyword Optimization (se the Focus Keyword Naturally, LSI Keywords) - Covers all relevant subtopics, examples, and related entities for full semantic coverage. - Demonstrates authority and expertise (E-E-A-T). - Follow Google’s SEO Guidelines For better Content, ensuring the information is valuable and helpful according to user needs, and free of unnecessary content or filler. - Ensure the output is free of grammar or spelling errors while maintaining readability Easy to Read. - Ensure content remains to the point, focused, and easy to understand words-sentence. make sure each sentence easy to understand clear which have proper meaning, aligning with user intent. - - - Avoid unnecessary expansions, keeping the content easy to understand and use short sentence for better readability. - Contains a 5–7 question FAQ section addressing common or strategic user questions make sure faq section main heading have pargraph 3-4 lines. - Optionally suggests meta title, meta description, and internal links. - Add real and authentic info value - In last before faq section Add offical website link(not clickable), phone number, visiting hours βœ“ Do not alter any heading levels. Every H2 must remain an H2, and every H3 must remain an H3. Preserve the exact markdown structure. And Heading should be in Bold. HTML TAGS ONLY:

,

,

,

, , , , , ,

, ,
, ,
    ,
  • ,
      ,
      ,