Welcome to Your Puppy Training Resource Hub!
If you’re wondering how to train your puppy the right way — you’re in the perfect place. We’re building a […]
private function image_fingerprint($src) { if (!$src) return ''; $src = preg_replace('/\?.*$/', '', $src); // strip query strings return md5(strtolower(trim($src))); } private function image_text_fingerprint($text) { $text = strtolower(trim((string)$text)); $text = preg_replace('/[^a-z0-9\s]+/i', ' ', $text); $text = preg_replace('/\s+/u', ' ', $text); if ($text === '') return ''; return md5($text); } ?php namespace SmartRankPro; if (!defined('ABSPATH')) { exit; } class Trust_Analyzer { public function analyze($post_id, $comparison_post_ids = []) { $html = Utils::get_post_content_html($post_id); $text = Utils::extract_text($html); $headings = Utils::extract_headings($html); $paras = Utils::extract_paragraphs($html); $sentences = Utils::split_sentences($text); $stats = Utils::sentence_length_stats($sentences); $phrase = Utils::repeated_phrases_ratio($text); $site_host = parse_url(home_url(), PHP_URL_HOST); $link_info = Utils::count_internal_links_in_body($html, $site_host); $anchor_ratio = Utils::anchors_identical_ratio($link_info['anchors']); $word_count = str_word_count($text); // Pillar scores (0-100), start from 100 then subtract. $structure = $this->score_structure($headings, $paras, $post_id); $human = $this->score_humanization($stats, $phrase, $paras); $semantic = $this->score_semantic($word_count, $headings, $paras); $meta = $this->score_meta($post_id, $comparison_post_ids); $media = $this->score_media($post_id, $comparison_post_ids); $links = $this->score_links($post_id, $headings, $link_info['count'], $anchor_ratio, $link_info['hub_only'], $link_info['pairs'] ?? []); $pillar_scores = [ 'structure' => $structure, 'humanization' => $human, 'semantic' => $semantic, 'meta' => $meta, 'media' => $media, 'internal_links' => $links, ]; $base = $this->weighted_base($pillar_scores); $automation = $this->automation_risk($post_id, $html, $text, $headings, $paras, $stats, $phrase, $comparison_post_ids); $penalty = $automation['penalty_points']; $final = max(0, min(100, round($base - $penalty))); // v1.4 tightened rules: when multiple automation-like patterns stack, apply trust caps $tc = (int)($automation['triggers_count'] ?? 0); if ($tc >= 5) $final = min($final, 54); else if ($tc >= 4) $final = min($final, 64); else if ($tc >= 3) $final = min($final, 74); $status = $this->status_band($final); $top_fixes = $this->top_fixes($pillar_scores, $automation, $word_count, $headings, $link_info); // Derived readiness $ai_readiness = round( (0.55*$human + 0.45*$semantic) ); $search_readiness = round( (0.45*$structure + 0.35*$links + 0.20*$meta) ); return [ 'schema_version' => 1, 'scan_timestamp' => Utils::current_time_iso(), 'post_id' => (int)$post_id, 'final_score' => (int)$final, 'status_band' => $status, 'automation_risk' => $automation['risk'], 'automation_penalty_points' => (int)$penalty, 'pillar_scores' => $pillar_scores, 'derived' => [ 'ai_readiness' => (int)$ai_readiness, 'search_readiness' => (int)$search_readiness, ], 'top_fixes' => $top_fixes, 'detected_patterns' => $automation['patterns'], 'debug' => [ 'word_count' => $word_count, 'sentence_stats' => $stats, 'phrase_ratio' => $phrase['ratio'], 'internal_links' => $link_info['count'], ], ]; } private function weighted_base($p) { // weights: structure 15, human 20, semantic 20, meta 10, media 10, links 15 => total 90. Normalize to 100. $w = [ 'structure' => 15, 'humanization' => 20, 'semantic' => 20, 'meta' => 10, 'media' => 10, 'internal_links' => 15, ]; $sum_w = array_sum($w); $acc = 0.0; foreach ($w as $k=>$wk) { $acc += ($p[$k] * $wk); } return round($acc / $sum_w); } private function status_band($score) { if ($score >= 85) return 'High Trust'; if ($score >= 70) return 'Trust Acceptable'; if ($score >= 50) return 'At Risk'; return 'Untrusted'; } private function score_structure($headings, $paras, $post_id) { $score = 100; $has_h2_or_h3 = false; foreach ($headings as $h) { if ($h['level'] === 2 || $h['level'] === 3) { $has_h2_or_h3 = true; break; } } if (!$has_h2_or_h3) $score -= 12; // Title repeated as first H2 $title = get_the_title($post_id); foreach ($headings as $h) { if ($h['level'] === 2) { if (mb_strtolower(trim($h['text'])) === mb_strtolower(trim($title))) $score -= 12; break; } } // Heading stacks: headings without paragraphs (template-ish) if (count($headings) >= 5 && count($paras) <= 2) $score -= 18; // Site-wide structure uniqueness (tightened in v1.4) $sig = $this->structure_signature($headings); if ($sig !== '') { $comparison_ids = Scanner::instance()->get_comparison_post_ids($post_id); $match = 0; $checked = 0; foreach (array_slice($comparison_ids, 0, 40) as $pid) { $h = Utils::extract_headings(Utils::get_post_content_html($pid)); $osig = $this->structure_signature($h); if ($osig === '') continue; $checked++; if (Utils::similarity_levenshtein_ratio($sig, $osig) > 0.88) $match++; } $prev = ($checked>0) ? ($match/$checked) : 0.0; if ($prev >= 0.30) $score -= 22; else if ($prev >= 0.18) $score -= 14; else if ($prev >= 0.10) $score -= 8; } return max(0, min(100, $score)); } private function score_humanization($stats, $phrase, $paras) { $score = 100; // Sentence stdev too low (stronger in v1.4) if ($stats['count'] >= 12) { if ($stats['stdev'] < 6) $score -= 30; else if ($stats['stdev'] < 10) $score -= 18; else if ($stats['stdev'] < 12) $score -= 10; } // Repeated phrase ratio if ($phrase['ratio'] > 0.08) $score -= 12; else if ($phrase['ratio'] > 0.05) $score -= 6; // Paragraph opener similarity $openers = []; foreach ($paras as $p) { $p = trim($p); if ($p === '') continue; $words = preg_split('/\s+/u', $p); $open = strtolower(implode(' ', array_slice($words, 0, 4))); if ($open !== '') $openers[] = $open; } if (count($openers) >= 8) { $counts = array_count_values($openers); arsort($counts); $top = reset($counts); $ratio = $top / count($openers); if ($ratio > 0.25) $score -= 18; } return max(0, min(100, $score)); } private function score_semantic($word_count, $headings, $paras) { $score = 100; if ($word_count < 300) $score -= 25; else if ($word_count < 450) $score -= 12; // meaningful sections: count H2/H3 $sections = 0; foreach ($headings as $h) { if ($h['level'] === 2 || $h['level'] === 3) $sections++; } if ($sections < 2) $score -= 12; // Semantic compression (lexical diversity too low) $body = implode(' ', (array)$paras); $ld = $this->lexical_diversity_ratio($body); if ($word_count >= 450) { if ($ld < 0.38) $score -= 22; else if ($ld < 0.43) $score -= 12; } return max(0, min(100, $score)); } private function score_meta($post_id, $comparison_post_ids) { $score = 100; $meta = Utils::get_meta_description($post_id); if (trim($meta) === '') $score -= 10; // Compare meta similarity across a sample and measure "boilerplate prevalence" $others = []; foreach ($comparison_post_ids as $pid) { $others[] = Utils::get_meta_description($pid); } $sim_threshold = 0.78; // tuned stricter than v1.3.0 $similar_count = 0; $checked = 0; $best = 0.0; foreach (array_slice($others, 0, 50) as $o) { if (!is_string($o) || trim($o) === '') continue; $checked++; $sim = Utils::similarity_levenshtein_ratio($meta, $o); if ($sim > $best) $best = $sim; if ($sim >= $sim_threshold) $similar_count++; } $prevalence = ($checked > 0) ? ($similar_count / $checked) : 0.0; // Meta boilerplate penalties: // - If your meta is very similar to many pages, this is a strong trust risk. if ($best > 0.85 && $prevalence >= 0.30) { $score -= 40; // heavy penalty for repeated boilerplate } else if ($best > 0.82 && $prevalence >= 0.15) { $score -= 28; } else if ($best > 0.80) { $score -= 15; } // Title duplicates/near duplicates $title = get_the_title($post_id); $titles = []; foreach ($comparison_post_ids as $pid) { $titles[] = get_the_title($pid); } $title_sim = $this->max_similarity($title, $titles); if ($title_sim > 0.90) $score -= 20; // Templated prefix/suffix detection $sample = array_slice($titles, 0, 20); $sample[] = $title; $ps = Utils::common_prefix_suffix_ratio($sample); if ($ps['prefix'] > 0.25 || $ps['suffix'] > 0.25) $score -= 10; // Meta cadence/length uniformity: if meta lengths too similar across sample $lens = []; foreach (array_slice($others, 0, 20) as $m) { $lens[] = mb_strlen(trim($m)); } $lens[] = mb_strlen(trim($meta)); if (count($lens) >= 8) { $mean = array_sum($lens)/count($lens); $var = 0.0; foreach ($lens as $l) $var += pow($l-$mean,2); $var /= count($lens); $stdev = sqrt($var); if ($stdev < 12) $score -= 8; } // Schema presence inside content can look templated if duplicated $html = Utils::get_post_content_html($post_id); $schema_scripts = 0; if (is_string($html) && $html !== '') { $schema_scripts = preg_match_all('/
Skip to contentIf you’re wondering how to train your puppy the right way — you’re in the perfect place. We’re building a […]
Instant Answer: Common mistakes to avoid when training a puppy include inconsistent commands, which can confuse the puppy and hinder
Table of Contents Effective Strategies for Puppy Obedience Training Success Understanding Puppy Behavior and Development Setting Up a Positive Training
Section Overview Benefits of Puppy Obedience Training for a Well-Behaved Dog Building a Strong Foundation for Good Behavior Enhancing Safety
Section Overview Benefits of Puppy Obedience Training for a Well-Behaved Dog Building a Strong Foundation for Good Behavior Enhancing Safety
In This Article Common Mistakes to Avoid in Puppy Obedience Training 1. Using Inconsistent Commands and Expectations 2. Punishing Instead
Quick Summary: Crate training is not strictly necessary for all puppies, but it is highly beneficial for their safety and
Instant Answer: To troubleshoot your puppy’s potty training issues, establish a consistent schedule for feeding and bathroom breaks to reinforce
Instant Answer: It typically takes between 4 to 6 months to fully train a puppy, but this can vary depending
Quick Take: Start with house training by establishing a consistent schedule for bathroom breaks and using positive reinforcement. Teach basic
Instant Answer: Your puppy may not respond to commands during training due to distraction, lack of focus, or insufficient training